Инверсия управления - это концепция возврата фреймворка в код пользователя.Это очень абстрактное понятие, и оно просто описывает разницу между библиотекой и каркасом, или его можно описать как «определяющую характеристику каркаса».Наш код вызывает библиотеку, а фреймворк контролирует наш код.Любой фреймворк предоставляет хуки, которые позволяют нам подключать наш код.
Инверсия управления - это шаблон, который можно применять, только если вы являетесь разработчиком фреймворка при создании фреймворка или, возможно, когда вы разрабатываете приложение, взаимодействующее срамочный код.Но IoC не применяется при работе исключительно с кодом приложения.
Акт зависимости от абстракций вместо реализаций называется инверсией зависимости, а инверсия зависимости может практиковаться как разработчиками приложений, так и разработчиками инфраструктуры.Так что то, что вы называете IoC, на самом деле является инверсией зависимости, и, как уже заметил Кшиштоф: то, что вы делаете, это не IoC.Теперь я буду обсуждать инверсию зависимости.
Существует две основные формы / реализации инверсии зависимости: сервисный локатор и внедрение зависимостей.
с шаблоном сервисный локатор Вы вызываете статическую фабрику из класса, который нуждается в зависимости.В общем, это выглядит так:
public class Service
{
public void SomeOperation() {
IDependency dependency =
ServiceLocator.GetInstance<IDependency>();
dependency.Execute();
}
}
Этот пример должен показаться вам знакомым, поскольку то, что вы делаете в своем методе Logon
: вы используете шаблон Service Locator.
Используя шаблон Dependency Injection , вы вводите все зависимости, которые нужны классу извне;желательно с помощью конструктора.Сам класс не несет ответственности за получение своих зависимостей.Эта ответственность перемещается вверх по стеку вызовов.Предыдущий класс выглядел бы так при использовании Dependency Injection:
public class Service
{
private readonly IDependency dependency;
public Service(IDependency dependency)
{this.dependency = зависимость;}
public void SomeOperation()
{this.dependency.Execute ();}}
Оба шаблона являются инверсией зависимости, поскольку в обоих случаях класс Service
не отвечает за создание зависимостей и не знает, какую реализацию он использует.Это просто говорит с интерфейсом.Оба шаблона дают вам гибкость по сравнению с реализациями, которые использует класс, и, таким образом, позволяют писать более гибкое программное обеспечение.
Однако существует много проблем с шаблоном Service Locator, и поэтому он считается анти-шаблоном.,Вы уже сталкиваетесь с этими проблемами, так как вам интересно, как Dependency Inversion (Service Locator в вашем случае) помогает вам с модульным тестированием.
Ответ заключается в том, что шаблон Service Locator не помогает с модульным тестированием.Напротив: это делает юнит-тестирование очень сложным.Позволяя классу вызывать ObjectFactory
, вы создаете жесткую зависимость между ними.Замена IAccountRepository
для тестирования также означает, что в вашем модульном тесте должен использоваться ObjectFactory
.Это затрудняет чтение ваших юнит-тестов.Но что более важно, поскольку ObjectFactory
является статическим экземпляром, все модульные тесты используют этот же экземпляр, что затрудняет выполнение тестов в изоляции и замену реализаций для каждого теста.
IВ прошлом я использовал шаблон Service Locator, и способ, которым я справлялся с этим, заключался в регистрации зависимостей в моем Service Locator, которые я мог изменять в потоке за ниткой (используя поле [ThreadStatic] под обложками).Это позволило мне выполнять свои тесты параллельно (что MSTest делает по умолчанию), сохраняя при этом изолированность тестов.Однако проблема в том, что это усложняется очень быстро, запутывает тесты всеми видами технических вещей, и это заставило меня потратить много времени на решение этих технических проблем, в то время как я мог бы писать больше тестов.
Реальным решением этих проблем является внедрение зависимостей.Как только вы вводите зависимости, в которых нуждается класс, через конструктор, все эти проблемы исчезают.Это не только делает очень ясным, какие зависимости нужны классу (без скрытых зависимостей), но и каждый модульный тест сам отвечает за внедрение зависимостей, в которых он нуждается.Это значительно облегчает написание тестов и избавляет вас от необходимости настраивать DI-контейнер в своих модульных тестах.
Дополнительная информация: Сервисный локатор - это анти-шаблон .