2017-05-17 5 views
1

私はSimple Injectorを使用しています。私は最初からDIを使用しているバックグラウンドプロセッサを持っています。それは実行するピックアップジョブ、およびそれらを実行します。しかし、各ジョブは、独自のスコープ内で実行しなければならないため、いくつかのコンテキスト依存性を無効にすることができます。たとえば、特定のセキュリティコンテキスト(作成元のセキュリティコンテキスト)内でジョブを実行する必要があるため、新しいスコープを開始してISecurityContextを上書きしてジョブを適切に保護する必要があります。スコープ内の依存関係を無効にする適切な方法

これを達成するために、新しいコンテナ(適切なISecurityContext)を作成し、スコープを開始してジョブを実行していましたが、これが適切かどうかはわかりません。

RUNJOB

private readonly Func<ISecurityContext, Container> _containerFactory; 

internal async Task RunJob(BackgroundJob job) { 
    var parameters = job.GetParameters(); 
    var securityContext = parameters.SecurityContext; 

    using (var container = _containerFactory(securityContext)) 
    using (AsyncScopedLifestyle.BeginScope(container)) { 
     // Run the job within this scope. 
    } 
} 

DIビット

container.RegisterSingleton<Func<ISecurityContext, Container>>(() => securityContext => { 
    var c = new Container(); 

    RegisterDependencies(c); 

    c.Options.AllowOverridingRegistrations = true; 
    c.Register<ISecurityContext>(() => securityContext, Lifestyle.Scoped); 

    return c; 
}); 

それは私に右に感じることはありませんが、私は正解が何であるかわかりません。

答えて

3

あなたが述べることによって何をしているかについての簡単なインジェクターのドキュメントwarns

警告:は、コンテナインスタンスの数を無限に作成しないでください(たとえば、1つの要求につき1つのインスタンスとして)。そうすることで、アプリケーションのパフォーマンスが低下します。ライブラリは、非常に限られた数のコンテナインスタンスを使用するように最適化されています。コンテナインスタンスの作成と初期化には大きなオーバーヘッドがありますが、初期化後はコンテナからの解決は非常に高速です。

一般的には、アプリケーションごとにのみ Containerインスタンスを作成する必要があります。これはパフォーマンスの観点からだけではありませんが、この種の「子コンテナ」の作成には、一般的には癖や欠陥があります。たとえば、アプリケーション全体で登録がシングルトンであることを確認する方法はありますか?

代わりに、ランタイム状態にコンテナを乱用しないでください。ただし、別の場所に保管してください。スコープ付きの状態の辞書としてScopeインスタンスを使用できますが、Scopedインスタンスとして登録され、次の例に示すようにスコープが作成された直後に初期化される、ISecurityContextの単純ラッパーを作成するのは簡単です。

// Can be part of your Composition Root 
internal sealed class SecurityContextWrapper : ISecurityContext 
{ 
    // One of the rare cases that Property Injection makes sense. 
    public ISecurityContext WrappedSecurityContext { get; set; } 

    // Implement ISecurityContext methods here that delegate to WrappedSecurityContext. 
} 


// Composition Root. Only have 1 container for the complete application 
c = new Container(); 

RegisterDependencies(c); 

c.Register<SecurityContextWrapper>(Lifestyle.Scoped); 
c.Register<ISecurityContext, SecurityContextWrapper>(Lifestyle.Scoped); 


// Job logic 
private readonly Container _container; 

internal async Task RunJob(BackgroundJob job) { 
    var parameters = job.GetParameters(); 
    var securityContext = parameters.SecurityContext; 

    using (AsyncScopedLifestyle.BeginScope(_container)) { 
     // Resolve the wapper inside the scope 
     var wrapper = _container.GetInstance<SecurityContextWrapper>(); 
     // Set it's wrapped value. 
     wrapper.WrappedSecurityContext = securityContext; 

     // Run the job within this scope. 
    } 
} 

あなたが国家としてScopeを使用している場合あるいは、あなたはSecurityContextWrapperのコンストラクタ引数としてScopeインスタンスを注入することができます。そのため、プロパティインジェクションを使用する必要はなくなりますが、SecurityContextWrapperはシンプルインジェクタに依存しています。

+0

優しく、ありがとうございます。これは間違いなく大きな改善です。 –

関連する問題