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

13-05-22 banq
         

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);
    }
}
<p>

其中IEventContainer是一个接口:

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

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

这个实现依赖于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;
}
<p>