2016-08-08 7 views
0

私は依存関係とIoCが初めてであるため疑いがあります。SimpleInjectorを使用してネストされたメソッドでDbContextを取得する方法

私には、(ビジネスロジックを使用する)ドメインレイヤーとデータレイヤーがあります。我々はリポジトリを実装せず、EFコアを直接使用します。 これはクラスライブラリプロジェクトで、AspNetCore Web API、WinForms、および別のフレームワークで使用します。

アイデアは、スコープ内で同じコンテキストを使用することです。

問題は、ネストされたメソッドの実行で同じコンテキストを取得できないということです。概念を完全に理解できなかったことが原因であると確信しています。

例:あなたはその抽象化することにより実装を登録

public class MyTest 
{ 
    public void TestContainer() 
    { 
     var parentContext = MyContainer.Container.GetInstance<MyContext>(); 
     TestParentAndChildContext(parentContext); 
    } 

    private void TestParentAndChildContext(MyContext parentContext) 
    { 
     var childContext = MyContainer.Container.GetInstance<MyContext>(); 
     Assert.AreEqual(parentContext, childContext); 
    } 
} 

public class MyContainer 
{ 
    public static Container Container 
    { 
     get { return container ?? (container = RegisterAndVerifyContainer()); } 
    } 

    private static Container RegisterAndVerifyContainer() 
    { 
     var container = new Container(); 
     container.Options.DefaultScopedLifestyle = new ExecutionContextScopeLifestyle(); 
     container.Register<DbContext, MyContext>(Lifestyle.Scoped); 

     container.Verify(); 

     return container; 
    } 
} 

答えて

0

シンプルインジェクターで。あなたの場合は、DbContextベースタイプでMyContextを登録しました。シンプルインジェクターのこの点から、誰かがDbContextを求める場合に備えてMyContextを構築する必要があることがわかります。あなたはその抽象化によってMyContextを登録しませんが、これは、あなたが直接MyContextの新しいインスタンスを要求する、しかし、実装ではなく、インターフェイスにあなたのケースで

プログラムの全体の目的でありますその抽象化を通じて要求するのではなく、これにより、Simple Injectorは登録された抽象リストの中のMyContextを検索します。 MyContextの登録がないので(ただし、DbContextがありますが、それはSimple Injectorとはまったく異なるタイプです)、Simple Injectorは不足している登録を追加しようとします。 MyContextは具象的であり、単一の分解可能なコンストラクタを持つため、これは成功します。デフォルトでは、Simple Injectorは登録されていない具体的なタイプをTransientとして解決します。

したがってMyContextは、直接要求されたときに一時的に解決されます。次のテストを変更することでこの問題を解決することができます

public void TestContainer() 
{ 
    using (MyContainer.Container.BeginExecutionContextScope()) { 
     var parentContext = MyContainer.Container.GetInstance<DbContext>(); 
     TestParentAndChildContext(parentContext); 
    } 
} 

private void TestParentAndChildContext(MyContext parentContext) 
{ 
    var childContext = MyContainer.Container.GetInstance<DbContext>(); 
    Assert.AreEqual(parentContext, childContext); 
} 

することは簡単なインジェクタは通常、ミスのこれらの種類を検知することに注意してください。 MyContextをそのDbContextベースタイプで登録しますが、タイプを呼び出すとMyContextを直接コンストラクタに挿入すると、Simple InjectorがShort Circuited Dependencyエラーをスローします。

解決策の前にVerify()を呼び出したためです(通常、アプリケーション内からGetInstanceを呼び出す必要はなく、すべてのオブジェクトグラフを前面に作成する必要があります)。あなたがMyContextを解決した後に(再び)Verifyを呼びたいときがありますが、例外がポップアップ表示さになります。

[TestMethod] 
public void TestContainer() 
{ 
    var container = MyContainer.Container.GetInstance<DbContext>(); 
    var parentContext = container.GetInstance<MyContext>(); 
    var childContext = container.GetInstance<MyContext>(); 

    // This call will fail 
    container.Verify(); 
} 
+0

感謝をあなたの知識を共有するため。 – Lucas

+0

あなたの知識を共有してくれてありがとう。 私はまだ多くのことを学ぶ必要があります。私の場合、これは最良の選択肢です。私はプレゼンテーション層へのアクセスが制限されており、ビジネス層とデータ層の下で作業し、いくつかのビジネスルールを実行しながら同じコンテキストを共有する必要があります。すべてのプロジェクトはクラスライブラリです。 ビジネスロジックからGetInstanceを呼び出してグラフを事前に構築できないのはなぜですか? – Lucas

+0

@Lucus:あなたは 'GetInstance'を呼び出しません。すべてのオブジェクトをアプリケーションの起動パス(Compostion Root)に登録します。また、すべてのインスタンスはコンストラクタインジェクションを使用して受信されます。深いオブジェクトグラップを構築します。 – Steven

関連する問題