Как известно, инверсия управления, это важный принцип SOLID, позволяющий писать слабо связанный код, повышая в разы гибкость кода.
Существует множество IoC-контейнеров (NInject, Unity, AutoFac и другие).
Для начинающих есть хорошая статья здесь.
Я же, в своих проектах использую TinyIoC - небольшие размеры, и то, что его использует проект NancyFx (Уроки по фреймворку nancy, и объяснение, что это, можно найти тут).
Первая задача - нам нужно объявить контейнер и что-то в него положить.
Проект у меня простой и демонстрационный, поэтому статического контейнера мне вполне хватает.
-
public static class AppContainer
-
{
-
private static TinyIoCContainer _instance;
-
public static TinyIoCContainer Instance
-
{
-
get { return _instance ?? RegisterInstance(); }
-
}
-
private static TinyIoCContainer RegisterInstance()
-
{
-
var instance = new TinyIoCContainer();
-
instance.Register<IYviEnumerable, YviEnumerable>();
-
_instance = instance;
-
return _instance;
-
}
-
}
В этом коде я в контейнере регистрирую некоторый интерфейс и реализацию, которая может поменяться в любой момент (достаточно написать класс, отнаследовавшись от IYviEnumerable и заменить ненужный нам класс).
Использование контейнера.
Типы, зарегистрированные в контейнере можно запросить напрямую из контейнера:
-
var yviEnumerable = AppContainer.Instance.Resolve<IYviEnumerable>();
Либо инъекцией типа в конструктор любого класса.
На этом пока всё.
Небольшая поправка.
Что делать, если нам требуется зарегистрировать в контейнере несколько классов одного и того же интерфейса?
-
instance.Register<IModule, StatisticLoader>("statistic");
-
instance.Register<IModule, Storage>("storage");
-
instance.Register<IModule, Http>("http");
Просто регистрируем:)
И резольвим список классов, зарегистрированных на один и тот же интерфейс:
-
IEnumerable<IModule> modules = container.ResolveAll<IModule>();