2016-08-08 31 views
0

由於我是依賴項和IoC的新手,我有一個疑問。如何使用SimpleInjector在嵌套方法中獲取DbContext

我有一個領域層(具有業務邏輯)和一個數據層。我們不實施知識庫,我們直接使用EF Core。 它是一個類庫項目,我們在一個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一個新實例,而不是通過抽象來請求它。這會導致簡單注入器在其註冊的抽象列表中查找MyContext。由於MyContext沒有註冊(雖然有DbContext雖然,但這是一個完全不同的簡單注射器類型),簡單注射器將嘗試添加缺少的註冊。這成功是因爲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); 
} 

請注意,簡單的噴油器通常會檢測這些類型的錯誤。如果您通過其DbContext基本類型註冊MyContext,但直接在類型的構造函數中注入MyContext,則簡單注入器在調用Verify()時將拋出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'。您在應用程序的啓動路徑中註冊所有對象(組合根)。並且所有實例都是使用構造函數注入接收的。你建立深刻的物體grapns。 – Steven