简体   繁体   English

带有Ninject的通用接口多次注入

[英]Generic Interface Multi-Injection with Ninject

For a project I'm working on, we're practicing domain driven design and using ninject as our IOC container. 对于我正在从事的项目,我们正在实践域驱动设计,并将ninject用作我们的IOC容器。 I'm trying to implement domain events similar to the approach described by Tony Truong here . 我正在尝试实现类似于Tony Truong 在此处描述的方法的领域事件。 I'm trying to use ninject without having to have a static service or referencing the Kernel outside the composition root. 我正在尝试使用ninject,而不必具有静态服务或在组合根外部引用内核。 I'm trying to do something like this 我正在尝试做这样的事情

/// <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>();
    }
}

The goal is to call all handlers registered for the type of the domain event instance passed in to the Dispatch method. 目标是调用为传递给Dispatch方法的域事件实例的类型注册的所有处理程序。 My problem is, the handlers array is empty when injected (I'm guessing because it's specifically looking for handlers bound to IDomainEventHandler<IDomainEvent>, not all handlers of types implementing IDomainEvent like I need). 我的问题是,注入时处理程序数组为空(我猜是因为它专门查找绑定到IDomainEventHandler <IDomainEvent>的处理程序,而不是像我需要的那样,并非所有实现IDomainEvent类型的处理程序)。

Instead of filtering for the correct handlers in your own code, you can use ninject to do that for you: 您可以使用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);
        }
    }
}

Pro-Tip: recommended design practice is to move the code dependent on IResolutionRoot (Ninject) to a factory-implementation in the composition root . Pro-Tip:建议的设计实践是将依赖于IResolutionRoot (Ninject)的代码移动到composition root中的工厂实现。 Instead of doing this manually, you can also make use of Ninject.Extensions.Factory 除了手动执行此操作外,您还可以使用Ninject.Extensions.Factory

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM