我有一个界面。
// Assembly: Common
public interface IEventHandler<TEvent> where TEvent : IDomainEvent
{
void HandleEvent(TEvent theEvent);
}
// Assembly: Common
public interface IDomainEvent
{
}
// Assembly: Common
public interface IEventDispatcher
{
void Register(IEventHandler<IDomainEvent> handler);
void Dispatch(IDomainEvent theEvent);
}
// Assembly: Membership
public sealed class MemberRegistered : IDomainEvent
{
// event properties
}
然后在我的ASP MVC 5项目中,我有事件的事件处理程序。
public sealed class MemberRegisteredHandler : IEventHandler<MemberRegistered>
{
public MemberRegisteredHandler(ApplicationUserManager userManager)
{
this.userManager = userManager;
}
private ApplicationUserManager userManager;
public void HandleEvent(MemberRegistered theEvent)
{
User user = new User(
theEvent.MemberId.ToString(),
theEvent.Username,
theEvent.PersonalInformation.Email);
this.userManager.CreateUserWithRandomPassword(user);
}
}
在我的启动课程
var container = new Container();
container.RegisterManyForOpenGeneric(
typeof(IEventHandler<>),
container.RegisterAll,
Assembly.GetExecutingAssembly());
container.Register<IEventDispatcher, SimpleEventDispatcher>();
有了这个,我如何获得event dispatcher
并将所有事件处理程序注册到其中?
我已经尝试了
var eventDispatcher = container.GetInstance<IEventDispatcher>();
foreach (var handler in container.GetAllInstances<IEventHandler<IDomainEvent>>())
{
eventDispatcher.Register(handler);
}
但它不起作用。 GetAllInstances方法没有返回任何内容。
Things to note:
IEventDispatcher
依赖于我的EF DbContext构造函数,我(现在)有两个上下文。 MembershipContext
和IdentityAccessContext
都来自EventDipatchingContext
,DbContext
来自EventDispatchingContext : DbContext
。
基本上是MembershipContext : EventDispatchingContext
然后是EventDispatchingContext
after its Commit() method is invoked
负责将事件委派给事件调度程序{{1}}。他们不会立即在我的域名申请中被解雇。我从Jimmy Bogard的博客那里得到了这个架构
https://lostechies.com/jimmybogard/2014/05/13/a-better-domain-events-pattern/
在这种情况下,我是否需要让IEventDispatcher成为单身人士?为什么呢?
如何正确地将处理程序注册到事件调度程序?
答案 0 :(得分:7)
不要在事件调度程序中“注册”事件处理程序。相反,您应该将事件调度程序实现作为composition root的一部分。这样,您可以安全地从调度程序中依赖容器,如下所示:
public class SimpleInjectorEventDispatcher : IEventDispatcher {
private readonly Container container;
public SimpleInjectorEventDispatcher(Container container) {
this.container = container;
}
public void Dispatch(IDomainEvent theEvent) {
var handlerType = typeof(IEventHandler<>).MakeGenericType(theEvent.GetType());
var handlers = this.container.GetAllInstances(handlerType);
foreach (dynamic handler in handlers) {
handler.HandleEvent((dynamic)theEvent);
}
}
}
请注意,IEventDispatcher
界面现在只包含Dispatch
方法。
在这种情况下,我是否需要让IEventDispatcher成为单身人士?为什么呢?
您不必将事件调度程序实现作为单例,但由于它没有依赖项且没有状态,因此将其设置为单例是明智的。这样,它的消费者也可以成为单身人士。单身人士越多越好。