2016-08-08 2 views
0

У меня есть сомнения, так как я новичок в зависимости и IoC.Как получить DbContext во вложенных методах с помощью SimpleInjector

У меня есть доменный уровень (с бизнес-логикой) и слой данных. Мы не реализуем репозитории, мы напрямую используем EF Core. Это проект библиотеки классов, мы используем его в веб-приложениях ASP.NET, 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

В простом Injector вы регистрируетесь реализацию по своей абстракции. В вашем случае вы зарегистрировали MyContext своим базовым типом DbContext. С этого момента Simple Injector будет знать, что ему нужно будет построить MyContext, если кто-то запросит DbContext. Это вся цель

программы на интерфейс, а не реализация

В вашем случае, однако, хотя вы зарегистрировать MyContext по своей абстракции, вы запрашиваете новый экземпляр MyContext непосредственно, вместо того, чтобы запрашивать его через его абстракцию. Это приводит к тому, что Simple Injector ищет MyContext в списке зарегистрированных абстракций. Поскольку нет регистрации для MyContext (есть для DbContext, хотя, но это совершенно другой тип, что такое простой инжектор), 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().

Причина, по которой вас не предупреждали об этом, заключается в том, что вы вызывали Verify() перед действием разрешения (обычно вы не должны вызывать GetInstance из вашего приложения, вместо этого вы должны построить все графические объекты). Но когда ты позвонишь Verify (снова) после разрешения MyContext вы увидите исключение выскакивают:

[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

Смежные вопросы