通用接口多注入与Ninject
问题描述:
对于我正在开发的一个项目,我们正在实践域驱动设计并将ninject用作我们的IOC容器。我试图实施类似于Tony Truong here所述方法的域事件。我正在尝试使用ninject,而不必在组合根之外拥有静态服务或引用内核。我试图做这样的事情通用接口多注入与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>();
}
}
目的是呼吁到调度方法传递域事件实例的类型注册的所有处理程序。我的问题是,注入处理程序数组是空的(我猜,因为它是专门寻找处理程序绑定到IDomainEventHandler <IDomainEvent>,而不是所有类型的实现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 )到composition root的工厂实施。 除了手动做这个的,你也可以利用Ninject.Extensions.Factory
最近这次的回答可以帮助你的问题似乎真的与你相似https://stackoverflow.com/a/46729694/1236044 – jbl
我已经搬到远离一个静态事件调度程序,并让我的域名返回事件。应用程序/整合层将发布/引发事件,因为另一个BC可能也对本BC中的事件感兴趣,而不仅仅是同一BC中的其他聚合。你仍然需要一些机制来执行发布,但是这些机制会被注入到你的控制器/应用程序层并从那里被使用。只是一个虽然:) –