使用IoC的事件调度库

时间:2016-03-13 20:15:49

标签: c# events nuget inversion-of-control

过去我构建了一个MessageDispatcher组件,它扫描一个程序集,查找用某些属性修饰的类型,并初始化每个属性的实例。然后,当任何对象被馈送到MessageDispatcher实例时,每个先前初始化的实例包含一个方法,该签名包含传递的对象的类型,该方法使用指定的参数触发所述方法。例如,在以下情况中:

[Listener]
public class MyListener
{
    MessageDispatcher _dispatcher; //Assigned elsewhere

    [MessageListener]
    public async Task DoSomething(int value)
    {
        var otherValue = await _dispatcher.Next<string>();
        Console.WriteLine($"{value} is {otherValue}.");
    }
}

以下代码初始化MyListener类的实例,调用DoSomething并打印“7 is okay。”:

var listener = new MessageDispatcher(typeof (ListenerAttribute));
listener.Dispatch(7);
listener.Dispatch("okay");

我想知道是否有任何专门用于或包含此类服务的库。它必须能够:

  • 扫描程序集并根据属性初始化类型。
  • 动态“订阅”某些类型
  • “等待”从调度程序中提取的值(与我的示例中的Next方法一样)。

1 个答案:

答案 0 :(得分:2)

(根据SO规则不允许使用库建议,这是尝试用实现来回答)

几乎任何IoC都可以实现这一点。他们所需要的只是能够使用属性或其他传统方式注册服务。

至于消息调度。只需创建IMessageHandler<TMessage>之类的界面即可。在应该处理消息的所有类上实现它。

示例:

public interface IMessageHandler<TMessage>
{
    void Handle(TMessage msg);
}

public class SomeService : IMessageHandler<UserCreated>
{
    //[.. all other methods ..]

    public void Handle(UserCreated msg)
    {
        // ...
    }
}

要发布消息,请创建调度程序。由于您使用的是容器,因此不必将其设置为静态容器。使用其中的容器(服务位置)来分发消息。现在有些偷看可能会说 oohh no,服务地点是反模式,buhuhuhu 。好吧不。并非在所有情况下。在这种情况下,它是类中的实现细节,具有识别和调用其他类的特定目的。

public interface IMessageDispatcher
{
    void Dispatch<TMessage>(TMessage msg);
}

// The actual implementation differs
// depending on your choice of container.
public class ContainerBasedMessageDispatcher : IMessageDispatcher
{
    Container _container;

    public ContainerBasedMessageDispatcher(Container container)
    {
        _container = container;
    }
    public void Dispatch<TMessage>(TMessage message)
    {
        using (var scope = container.BeginLifetimeScope())
        {
            var handlers = scope.Resolve<IEnumerable<IMessageHandler<TMessage>>();
            foreach (var handler in handlers)
            {
                handler.Handle(message);
            }
        }
    }
}

代码直接用SO编写。所以它可能无法正常工作。但希望它能给你一个如何实现你想要的想法。

用法:

public class UserService
{
   IMessageDispatcher _dispatcher;

   public UserService(IMessageDispatcher dispatcher)
   {
       _dispatcher = dispatcher;
   }

   public void Create(User user)
   {
       //[...]


       _dispatcher.Dispatch(new UserCreated(user.Id));
   }
}

然而,这不会动态地允许您订阅您想要的内容。如果忽略不需要的消息是不可行的。那么这个答案不适合你。