0

问题

在我的域层程序集中,我存储了两个接口:

public interface IDomainEvent { }

public interface IHandle<T> where T: IDomainEvent, new()

EventDispatcher类也在那里定义:

public static class EventDispatcher {
    [ThreadStatic]
    private static List<Delegate> actions;
    [ThreadStatic]
    private static List<Object> handlers;

    public static List<Object> Handlers { 
        get { return handlers; } 
        set { handlers = value; } 
    }

    public static void Register<T>(Action<T> callback) where T : IDomainEvent, new() {
        if(null == actions) {
            actions = new List<Delegate>();
            actions.Add(callback);
        }
    }

    public static void ClearCallbacks() {
        actions = null;
    }

    public static void Raise<T>(T @event) where T : IDomainEvent, new() {
        if(null != Handlers) {
            foreach(var handler in Handlers.Where(h => h is IHandle<T>)) {
                ((IHandle<T>)handler).Handle(@event);
            }
        }

        if(null != actions) {
            foreach(var action in actions) {
                if(action is Action<T>) {
                    ((Action<T>)action)(@event);
                }
            }
        } // if(null != actions) {
    }
}

表示层组件中有一个模块:

public class EventDispatchingModule : NinjectModule {

    public override void Load() {

        // EventDispatcher.Handlers = this.Kernel.GetAll(IHandle<T>); Can't do that!
        // Bind<IHandle<CarHasBeenRegisteredEvent>>().To<CarHasBeenRegisteredHandler();
    }
}

所以我不能Kernel.GetAll(IHandle<T>)在那里打电话,因为它不能解析T参数。

我怎么解决这个问题?

谢谢!

4

2 回答 2

2

无需使用模块(我没有使用 ninject,但类似的东西):

// Put these in the domain project

public class EventDispatcher
{
    private static IEventDispatcher _dispatcher;

    public static void Setup(IEventDispatcher dispatcher)
    {
        _dispatcher = dispatcher;
    }

    public static void Dispatch<T>(T domainEvent) where T : IDomainEvent
    {
        _dispatcher.Dispatch<T>(domainEvent);
    }
}

public interface IEventDispatcher
{
    public void Dispatch<T>(T domainEvent) where T : IDomainEvent;
}


// and this one in the project which has Ninject

public class NinjectEventDispatcher : IEventDispatcher
{
    private static IKernel _container;

    public NinjectEventDispatcher(IKernel container)
    {
        _container = container;
    }

    public void Dispatch<T>(T domainEvent) where T : IDomainEvent
    {
        foreach (var listener in _container.GetAll<IHandle<T>>())
        {
            listener.Handle(domainEvent);
        }
    }
}

// And after the container have been configured:
EventDispatcher.Setup(new NinjectEventDispatcher(_container));

但我不知道 ninject 如何处理作用域对象(可能也想接收事件)。

我的容器内置了域事件,请在本文中阅读更多内容:http: //www.codeproject.com/Articles/440665/Having-fun-with-Griffin-Container

更新:

我更新了代码示例,使域项目不知道 Ninject。

您没有在此代码中使用服务位置。事件分派器的内部结构是。即您的任何代码都不受它的影响。

于 2012-08-31T12:44:05.890 回答
2

您可以使用以下代码获取所有处理程序

Kernel.GetAll(typeof (IHandle<>));

但无论如何,在 NInjectModule 中加载所有 IHander 并不是一个好主意,因为您不知道是否已经加载了其他模块(并且其他模块也可以注册 Handler)。我建议使 EventDispatcher 类不是静态的并将其注册在您需要的范围内(如果您需要每个请求的新处理程序 - 在请求范围内,否则 - 在单例范围内。您可以使用构造函数注入的处理程序,例如:

Kerner.Bind<EventDispatcher>().ToSelf()
      .InRequestScope()
      .WithConstructorArgument("handlers", c => c.Kernel.GetAll(typeof(IHandler<>)))

希望这可以帮助

于 2012-08-31T13:24:57.540 回答