对于我正在从事的一个项目,我们正在练习领域驱动设计并使用 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
您可以使用 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