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

时间:2015-08-11 10:04:11

标签: asp.net-mvc event-handling domain-driven-design 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
}

然后在我的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构造函数,我(现在)有两个上下文。 MembershipContextIdentityAccessContext都来自EventDipatchingContextDbContext来自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成为单身人士?为什么呢?

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

1 个答案:

答案 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成为单身人士?为什么呢?

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