使用 Ninject and ASP.Net Web API 實現Domain Events

banq發表於2013-05-22
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 class="indent">


其中IEventContainer是一個介面:

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

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 class="indent">


這個實現依賴於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 class="indent">

相關文章