2017-07-31 3 views
0

DbContextをコアドメインハンドラに1回アクティブ化するスコープを含めるには、アプリケーション内にNinjectカスタムスコープを使用したいと思います。しかし、CommandScopeオブジェクトがNinjectの一部であるINotifyWhenDisposedインターフェイスを実装しているため、私のドメイン内のNinjectに依存したくないので、問題があります。決定的な処理のためにNinjectスコープオブジェクトを挿入する

Ninjectファクトリを使用してIScopeFactoryを公開することやFuncの依存関係など、コードに依存することを成功させるために、さまざまな方法を試しました。後者の場合、問題は、バインディングターゲットがIDisposable自体ではなくFuncであるため、NinjectはINotifyWhenDisposed.Disposeイベントを終了させないということです。

とにかく、私が達成しようとしているコードです。

のIoC

自分のドメイン内
Kernel 
    .Bind<MyDbContext>() 
    .ToSelf() 
    .InScope(x => CommandScope.Current) 
    .OnDeactivation(x => x.SaveChanges()); 

CommandScope

public class CommandScope : INotifyWhenDisposed 
{ 
    public event Dispose; 

    public bool IsDisposed { get; private set; } 

    public static CommandScope Current { get; private set; } 

    public static CommandScope Create() 
    { 
     CommandScope result = new CommandScope(); 
     Current = result; 
     return result; 
    } 

    public void Dispose() 
    { 
     IsDisposed = true; 
     Current = null; 
     Dispose?.Invoke(this, EventArgs.Empty); 
    } 
} 

...

public class Pipeline<TRequest, TResponse> 
{ 
    readonly IRequestHandler<TRequest, TResponse> innerHandler; 

    public Pipeline(IRequestHandler<TRequest, TResponse> handler) 
    { 
     innerHandler = handler; 
    } 

    public TResponse Handle(TRequest request) 
    { 
     using(CommandScope.Create()) 
     { 
      handler.Handle(request); 
     } 
    } 
} 
+0

しかし、Pipelineクラスはインフラストラクチャコードなので、ドメインロジックを含むプロジェクトとは異なるプロジェクトに展開することができます。それとも別の問題がありますか? –

答えて

1

あなたはDecoratorパターンを使用することができます(インターフェースが必要)のみデコレータを実装していINotifyWhenDisposedインターフェイス - コンポジションルートにデコレータを配置する - そこにあなたはとにかくニンジェットリファレンスが必要です。

代わりに、Func Factoryを使用して、IDisposableを作成してください。これはINotifyWhenDisposedを実装しています(消費ライブラリはこれについて知る必要はありません)。コンポジションルートのインスタンスにアクセスするときは、まだそれをINotifyWhenDisposedにキャストすることができます(実際は不要かもしれません)。たとえば:

.InScope(x => (INotifyWhenDisposed)CommandScope.Current) 

設計上のコメントは:工場と実際の範囲:私はhighylう二つのクラスにCommandScopeを分割することをお勧めします。 また、長期的には、新しいスコープ(Createによって作成されたもの)が、まだ処分されていない古いスコープを置き換えないようにすることで、頭痛を大幅に軽減できます。そうでなければ、あなたが紹介したリークを見逃してしまう可能性があります。 NinjectのICacheからスコープオブジェクトをクリア

0

はスコープによって制御されるすべてのインスタンスを閉じて、処分するNinjectを強制します:

var activationCache = Kernel.Get<Ninject.Activation.Caching.ICache>(); 
activationCache.Clear(CommandScope.Current); 

また、あなたのシングルトンパターンCommandScopeへのより良い代替手段を持っているNamedScope extensionを考慮することができます。

関連する問題