域事件模式单点到队列事件

时间:2013-03-28 19:22:02

标签: c# generics domain-events

我在这里提出一个问题:Raising Domain Events For Multiple Subscribers并且答案引导我进入以下模式,我可以像这样拥有一个IEventPublisher:

public interface IEventPublisher<T>
{
    void Publish(T data);
}

和像这样的IEventSubscriber:

public interface IEventSubscriber<T>
{
    void Handle(T data);
}

这个问题是我需要将每个发布者的实例传递给构造函数,如下所示:

public Service(IEventPublisher<ThingyChangedEvent> publisherThingyChanged)
{
   // Set publisher to local variable
}

// then call this in a method
_publisherThingyChanged.Publish(new ThingyChangedEvent { ThingyId = model.Id});

我希望能够做的是拥有一个包含任何IEventPublishers的通用发布者,所以我可以调用类似的东西:

_genericPublisher.Publish(new ThingyChangedEvent { ThingyId = model.Id});

我无法弄清楚如何做到这一点,因为我无法传递IEventPublisher的集合而不定义T,因为在此示例中为ThingyChangedEvent,而我想要的是根据传递给的类型来确定发布者通用出版商。

任何建议都非常感谢。

修改

确定使用下面的答案和来自这里的一些信息:http://www.udidahan.com/2009/06/14/domain-events-salvation/我想出了以下内容,但它并不完全存在:

public interface IEventManager
{
  void Publish<T>(T args) where T : IEvent;
}

public class EventManager:IEventManager   {     Autofac.ILifetimeScope _container;

public EventManager(Autofac.ILifetimeScope container)
{
  _container = container;
}

//Registers a callback for the given domain event
public void Publish<T>(T args) where T : IEvent
{
  var subscribersProvider = _container.Resolve<IEventSubscribersProvider<T>>();
  foreach (var item in subscribersProvider.GetSubscribersForEvent())
  {
    item.Handle(args);
  }
}

}

我现在可以在autofac解析的构造函数中获取IEventManager eventManager的实例,并按如下方式调用它:

_eventManager.Publish<ThingyChangedEvent>(new ThingyChangedEvent() { ThingyId = Guid.NewGuid() });

以下是我对此解决方案不喜欢的内容:

我不想在构造函数中使用ILifetimeScope的实例,我希望能够获取IEventSubscribersProvider的集合,但如果我要求说,autofac将无法解决此问题:

 IEnumerable<IEventSubscribersProvider<IEvent>> 

如果我将类型传递给Publish并调用:

,我只能解决它
Resolve<IEventSubscribersProvider<T>>.

第二个问题不是一个大问题,但能够调用发布而不必像这样传递类型会很好:

_eventManager.Publish(new ThingyChangedEvent() { ThingyId = Guid.NewGuid() });

我认为如果有人对如何解决这两个问题有任何建议,特别是问题1,因为我不喜欢在不同的项目中依赖Autofac。我能想到的唯一一个是某种类型的管理器类,它明确地采用了我需要的内容如下:

public SomeConstructor(
    IEventSubscribersProvider<ThingyChangedEvent> thingChangedSubscribeProviders,
    IEventSubscribersProvider<SomeOtherEvent> someOtherSubscribeProviders,
    etc....)
{
     // Maybe take the EventManager as well and add them to it somehow but would be
     // far easier to take a collection of these objects somehow?
}

非常感谢任何建议。

编辑2

经过大量研究并观察Autofac Generic Service resolution at runtime后,我不确定自己能达到什么目的。我能想出的最佳解决方案是:

public interface IEventSubscribersProviderFactory : Amico.IDependency
{
  IEventSubscribersProvider<T> Resolve<T>() where T : IEvent;
}

public class EventSubscribersProviderFactory : IEventSubscribersProviderFactory
{ 
  Autofac.ILifetimeScope _container;

  public EventSubscribersProviderFactory(Autofac.ILifetimeScope container)
  {
    _container = container;
  }

  public IEventSubscribersProvider<T> Resolve<T>() where T : IEvent
  {
    return _container.Resolve<IEventSubscribersProvider<T>>();
  }
}

然后让EventManager在构造函数中使用IEventSubscribersProviderFactory来删除该项目对Autofac的依赖。

我现在要继续这样做,但希望能长期找到更好的解决方案。

0 个答案:

没有答案