Simple Injector:如何将事件处理程序实例注册到事件调度程序

Jai*_*cap 4 asp.net-mvc domain-driven-design event-handling publish-subscribe simple-injector

我有一个界面.

// 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
}
Run Code Online (Sandbox Code Playgroud)

然后在我的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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

在我的Startup课程上

var container = new Container();
container.RegisterManyForOpenGeneric(
               typeof(IEventHandler<>),
               container.RegisterAll,
               Assembly.GetExecutingAssembly());

container.Register<IEventDispatcher, SimpleEventDispatcher>();
Run Code Online (Sandbox Code Playgroud)

有了这个,我如何获得event dispatcher并注册所有事件处理程序?

我试过了

var eventDispatcher = container.GetInstance<IEventDispatcher>();

foreach (var handler in container.GetAllInstances<IEventHandler<IDomainEvent>>())
{
    eventDispatcher.Register(handler);
}
Run Code Online (Sandbox Code Playgroud)

但它不起作用.GetAllInstances方法没有返回任何内容.

Things to note:IEventDispatcher是我的EF DbContext构造函数的依赖,我(现在)有两个上下文.MembershipContextIdentityAccessContext其中两个来源于EventDipatchingContext从派生DbContext.基本上它的EventDispatchingContext : DbContextMembershipContext : EventDispatchingContext

EventDispatchingContext负责委派事件事件调度after its Commit() method is invoked.他们不会立即在我的域名申请中被解雇.我从Jimmy Bogard的博客那里得到了这个架构

https://lostechies.com/jimmybogard/2014/05/13/a-better-domain-events-pattern/

在这种情况下,我是否需要使IEventDispatcher成为单例?为什么?

如何正确地将处理程序注册到事件调度程序?

Ste*_*ven 7

不要在事件调度程序中"注册"事件处理程序.相反,您应该将事件调度程序实现作为组合根的一部分.这样,您可以安全地从调度程序中依赖容器,如下所示:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,IEventDispatcher界面现在只包含一个Dispatch方法.

在这种情况下,我是否需要使IEventDispatcher成为单例?为什么?

您不必将事件调度程序实现设置为单例,但由于它没有依赖关系且没有状态,因此将其设置为单例是明智的.这样,它的消费者也可以成为单身人士.越多的单身人士越多越好.