2016-08-08 30 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