2017-10-20 5 views
0

私が取り組んでいるプロジェクトでは、ドメイン駆動型デザインを実践し、ninjectをIOCコンテナとして使用しています。私は、Tony Truong hereによって記述されたアプローチと同様のドメインイベントを実装しようとしています。私は静的なサービスを持ったり、コンポジションルートの外側でカーネルを参照したりせずに、ninjectを使用しようとしています。私は目標は、発送方法に渡されたドメインのイベントインスタンスのタイプに登録されているすべてのハンドラを呼び出すことです Ninjectを使用した汎用インターフェイスのマルチインジェクション

/// <summary> 
/// Service to dispatch domain events to handlers. 
/// </summary> 
public class NinjectDomainEventDispatcher : IDomainEventDispatcher 
{ 
    /// <summary> 
    /// Array containing domain event handler registrations. 
    /// </summary> 
    private readonly IDomainEventHandler<IDomainEvent>[] _handlers; 

    /// <summary> 
    /// Initializes a new instance of the <see cref="NinjectDomainEventDispatcher"/> class. 
    /// </summary> 
    /// <param name="handlers">Registered domain event handlers.</param> 
    public NinjectDomainEventDispatcher(IDomainEventHandler<IDomainEvent>[] handlers) 
    { 
     _handlers = handlers; 
    } 

    /// <summary> 
    /// Dispatch domain event to subscribed handlers. 
    /// </summary> 
    /// <typeparam name="T">Type of domain event to dispatch.</typeparam> 
    /// <param name="domainEvent">Domain event to dispatch.</param> 
    public void Dispatch<T>(T domainEvent) where T : IDomainEvent 
    { 
     foreach (var handler in _handlers.Where(x => x.GetType() == typeof(IDomainEventHandler<T>))) 
     { 
      handler.Handle(domainEvent); 
     } 
    } 
} 

/// <summary> 
/// Module that will be used for the registration of the domain event handlers 
/// </summary> 
public class DomainEventHandlerModule : NinjectModule 
{ 
    /// <summary> 
    /// The method that will be used to load the ninject registration information. 
    /// </summary> 
    public override void Load() 
    { 
     Bind<IDomainEventDispatcher>().To<NinjectDomainEventDispatcher>(); 
     Bind<IDomainEventHandler<ConcreteDomainEvent>>().To<ConcreteDomainEventHandler1>(); 
     Bind<IDomainEventHandler<ConcreteDomainEvent>>().To<ConcreteDomainEventHandler2>(); 
     Bind<IDomainEventHandler<AnotherConcreteDomainEvent>>().To<AnotherConcreteDomainEventHandler1>(); 
     Bind<IDomainEventHandler<AnotherConcreteDomainEvent>>().To<AnotherConcreteDomainEventHandler2>(); 
    } 
} 

このような何かをしようとしています。私の問題は、ハンドラ配列が空になっている(IDomainEventハンドラがIDomainEventHandlerにバインドされているため、IDomainEvent >にIDomainEventを実装しているすべてのハンドラではありません)。代わりに、独自のコードで正しいハンドラのフィルタリングの

+0

この最新の回答はあなたの質問に本当に似ているように思われるかもしれません。htt38://stackoverflow.com/a/46729694/1236044 – jbl

+0

私は離れました静的イベントのディスパッチャであり、私のドメインではなくイベントを返します。アプリケーション/統合レイヤーは、別のBCも同じBCの他の集約ではなく、このBCのイベントにも関心がある可能性があるので、イベントを公開/上げることになります。パブリッシングを実行するにはまだ何らかのメカニズムが必要ですが、それはコントローラ/アプリケーションレイヤに注入され、そこから使用されます。ちょうど:) –

答えて

0

、あなたはあなたのためにそれを行うためにninject使用することができます。

public class NinjectDomainEventDispatcher : IDomainEventDispatcher 
{ 
    private readonly IResolutionRoot resolutionRoot; 

    public NinjectDomainEventDispatcher(IResolutionRoot resolutionRoot) 
    { 
     this.resolutionRoot = resolutionRoot; 
    } 

    public void Dispatch<T>(T domainEvent) where T : IDomainEvent 
    { 
     var handlers = this.resolutionRoot.GetAll<IDomainEventHandler<T>>(); 
     foreach (var handler in handlers) 
     { 
      handler.Handle(domainEvent); 
     } 
    } 
} 

プロヒント:推奨設計手法は、(IResolutionRootに依存したコードを移動することNinjectです)をcomposition rootの工場実装に変更します。 これを手動で行う代わりに、Ninject.Extensions.Factory

関連する問題