使用 Ninject and ASP.Net Web API 实现Domain Events

         
banq
13-05-22 384

Domain Events with Ninject and ASP.Net Web API | Contented Coder Blog

该博客谈论了使用Ninject依赖注射的方法实现领域事件,个人认为这与DCI实现方式非常类似,都是结构上组合。

假设Domain events代码如下:

public static class DomainEvents
{
/// <summary>
/// The _actions.
/// </summary>
/// <remarks>Marked as ThreadStatic that each thread has its own callbacks</remarks>
[ThreadStatic]
private static List<Delegate> _actions;

/// <summary>
/// The container
/// </summary>
public static IEventContainer Container;

/// <summary>
/// Registers the specified callback for the given domain event.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="callback">The callback.</param>
public static void Register<T>(Action<T> callback) where T : IDomainEvent
{
if (_actions == null)
_actions = new List<Delegate>();

_actions.Add(callback);
}
/// <summary>
/// Raises the specified domain event and calls the event handlers.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="domainEvent">The domain event.</param>
public static void Raise<T>(T domainEvent) where T : IDomainEvent
{
if (Container != null)
foreach (var handler in Container.Handlers(domainEvent))
handler.Handle(domainEvent);

// registered actions, typically used for unit tests.
if (_actions != null)
foreach (var action in _actions)
if (action is Action<T>)
((Action<T>)action)(domainEvent);
}
}


其中IEventContainer是一个接口:

public interface IEventContainer
{
IEnumerable<IDomainEventHandler<T>> Handlers<T>(T domainEvent)
where T : IDomainEvent;
}

IEventContainer的NInject实现代码如下:

public class NinjectEventContainer : IEventContainer
{
private readonly IKernel _kernerl;

public NinjectEventContainer(IKernel kernal)
{
_kernerl = kernal;
}

public IEnumerable<IDomainEventHandler<T>> Handlers<T>(T domainEvent) where T : IDomainEvent
{
return _kernerl.GetAll<IDomainEventHandler<T>>();
}
}


这个实现依赖于DI核心IKernerl,关键的代码如下:

private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

// this is our concrete implementation of handler for winner selected event
kernel.Bind<IDomainEventHandler<WinnerSelectedEvent>>().To<WinnerSelectedHandler>();

GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);

// ** WIRE UP DOMAIN EVENTS CONTAINER **
DomainEvents.Container = new NinjectEventContainer(kernel);

return kernel;
}