通用接口多注入与 Ninject



对于我正在从事的一个项目,我们正在练习领域驱动设计并使用 ninject 作为我们的 IOC 容器。我正在尝试实现类似于 Tony Truong 在这里描述的方法的域事件。我正在尝试使用 ninject,而不必使用静态服务或在组合根目录之外引用内核。我正在尝试做这样的事情

/// <summary>
/// Service to dispatch domain events to handlers.
/// </summary>
public class NinjectDomainEventDispatcher : IDomainEventDispatcher
{
    /// <summary>
    /// Array containing domain event handler registrations.
    /// </summary>
    private readonly IDomainEventHandler<IDomainEvent>[] _handlers;
    /// <summary>
    /// Initializes a new instance of the <see cref="NinjectDomainEventDispatcher"/> class.
    /// </summary>
    /// <param name="handlers">Registered domain event handlers.</param>
    public NinjectDomainEventDispatcher(IDomainEventHandler<IDomainEvent>[] handlers)
    {
        _handlers = handlers;
    }
    /// <summary>
    /// Dispatch domain event to subscribed handlers.
    /// </summary>
    /// <typeparam name="T">Type of domain event to dispatch.</typeparam>
    /// <param name="domainEvent">Domain event to dispatch.</param>
    public void Dispatch<T>(T domainEvent) where T : IDomainEvent
    {
        foreach (var handler in _handlers.Where(x => x.GetType() == typeof(IDomainEventHandler<T>)))
        {
            handler.Handle(domainEvent);
        }
    }
}
/// <summary>
/// Module that will be used for the registration of the domain event handlers
/// </summary>
public class DomainEventHandlerModule : NinjectModule
{
    /// <summary>
    /// The method that will be used to load the ninject registration information.
    /// </summary>
    public override void Load()
    {
        Bind<IDomainEventDispatcher>().To<NinjectDomainEventDispatcher>();
        Bind<IDomainEventHandler<ConcreteDomainEvent>>().To<ConcreteDomainEventHandler1>();
        Bind<IDomainEventHandler<ConcreteDomainEvent>>().To<ConcreteDomainEventHandler2>();
        Bind<IDomainEventHandler<AnotherConcreteDomainEvent>>().To<AnotherConcreteDomainEventHandler1>();
        Bind<IDomainEventHandler<AnotherConcreteDomainEvent>>().To<AnotherConcreteDomainEventHandler2>();
    }
}

目标是调用为传递给 Dispatch 方法的域事件实例的类型注册的所有处理程序。我的问题是,处理程序数组在注入时是空的(我猜是因为它专门寻找绑定到 IDomainEventHandler 的处理程序,而不是所有实现 IDomainEvent 类型的处理程序,就像我需要的那样)。

您可以使用 ninject 为您执行此操作,而不是在您自己的代码中筛选正确的处理程序:

public class NinjectDomainEventDispatcher : IDomainEventDispatcher
{
    private readonly IResolutionRoot resolutionRoot;
    public NinjectDomainEventDispatcher(IResolutionRoot resolutionRoot)
    {
        this.resolutionRoot = resolutionRoot;
    }
    public void Dispatch<T>(T domainEvent) where T : IDomainEvent
    {
        var handlers = this.resolutionRoot.GetAll<IDomainEventHandler<T>>();
        foreach (var handler in handlers)
        {
            handler.Handle(domainEvent);
        }
    }
}

专业提示:推荐的设计实践是将依赖于IResolutionRoot(Ninject)的代码移动到组合根中的工厂实现中。除了手动执行此操作,您还可以使用 Ninject.Extensions.Factory

最新更新