在Ninject模块中获取已解析的类型

时间:2012-08-31 12:19:49

标签: c# asp.net-mvc ninject event-dispatching

问题

在我的域层组件中我存储了两个接口:

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参数。

我如何解决这个问题?

谢谢!

2 个答案:

答案 0 :(得分: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。

您没有使用此代码的服务位置。事件调度员的内部是。即你的代码都没有受到它的影响。

答案 1 :(得分:2)

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

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

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

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

希望这有帮助