2012-08-31 12 views
0

問題獲得一個Ninject模塊內解決類型

在我 域層組件

我存儲兩個接口:

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

無需使用一個模塊(我沒有用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的。

您未在此代碼中使用服務位置。事件調度員的內部是。即您的代碼都不受其影響。

+0

你看我不想做內核的副本,使用服務位置這個類駐留在領域層/單獨的程序集中我嘗試了一個類似於你的解決方案:我使用動態屬性來獲取一個內核的副本如果這樣做,你需要添加一個對Ninject程序集的引用到一個域層,這樣它可以調用擴展方法'GetAll(serviceArgs)'並且我知道你的容器,但我只是想試着用這種方式) – lexeme

+0

@brick:我已經更新了代碼,並解決了您的服務位置問題。 – jgauffin

2

你可以得到所有的處理程序與下面的代碼

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

但無論如何,這不是好主意,加載所有IHanders在NInjectModule,因爲你不知道另一個模塊已裝入或沒有(和其他模塊可以註冊處理程序也)。 我建議讓EventDispatcher類不是靜態的,其註冊範圍,你需要(如果你需要爲每個請求新的處理器 - 在請求範圍內,否則 - 在單身範圍處理程序,你可以像構造注入:

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

希望這會有所幫助