Wiki
Clone wikiDIContainer / Home
Контейнер самостоятельно создает зарегистрированные классы и предоставить необходимые им зависимости. От нас требуется создать контейнер ,
var container = new Container();
using SimpleDIContainer.UserLayer;
Далее проиллюстрирую на примере некоторого тестового класса, куда контейнер будет внедрять зависимости, если это указано в конфигурации и класс зарегистрирован в контейнере.
public class Test1:ITest1 { public Test1(ITestInterface testInterface,ITest3 test3,List<ITest4> test41)* { //когда контейнер будет создавать объект, он внедрит все необходимые //зависимости в конструктор, при условии, что они были зарегистрированы } private IList<ITest4> _tests{get;set;}// не сможем в этом место внедрить,тк приватное проперти public IList<ITest4> tests{get;set;}//при конфигурации после создания объекта контейнер внедрит в проперти //нужное значение, если это прописать в конфигурации public void BindMethod(IList<ITest4> tests) { //можно внедрить агрументы в метод , после создания объекта метод будет //вызван с необходимыми аргументами , если это прописать в конфигурации } }
Биндинг
Мы можем зарегистрировать объект по его интерфейсу:
container.Bind<ITest4, Test4>();
Мы можем зарегистрировать объект как конкретную реализацию:
container.BindInstance<Test1>();
Также на один интерфейс можно зарегистрировать несколько реализаций, ровно как и зарегистрировать их на один абстрактный класс или класс-родитель.
container.Bind<ITest4, Test4>(); container.Bind<ITest4, Test41>();
Типы жизненных циклов
После регистрации типа, мы должны указать способ предоставления его нам, например вот так:
container.Bind<ITest4, Test4>().AsSingle();
AsSingle - по умолчанию будет применен , если мы не указали иного, на каждое обращение к ITest4 будет выдаваться один и тот же инстанс объекта. Инстанс будет создан при первом обращении. AsTransient - на каждое обращение создаем новый инстанс.
Ленивое/не ленивое создание
Конструкции выше не приведут к созданию объекта незамедлительно, тк по умолчанию объект создается только после обращения к нему(например при внедрении в другой объект). Чтобы создать сразу, нужно вызвать ActivateNonLazy вот так:
container.Bind<ITest4, Test4>().AsSingle().ActivateNonLazy();
Внедрения в проперти
Внедрение в проперти рекомендуется делать при наличии локального умолчания, также обязательные зависимости рекомендуется внедрять через конструктор. В контейнере сознательно отказались от кастомных атрибутов для методов и пропертей, чтобы не связывать пользовательский код с кодом контейнера. Какие именно проперти внедрять - мы задаем в месте создания и конфигурации контейнера
container.Bind<ITest1, Test1>().BindAllProperties().AsSingle().ActivateNonLazy();
container.Bind<ITest1, Test1>().BindProperty("Test1").AsSingle().ActivateNonLazy();
Внедрение в метод
Внедрение в метод может быть актуально например при использовании фабричного метода.
container.Bind<ITest1, Test1>().BindMethod("BindMethod").AsSingle().ActivateNonLazy();
Ручное внедрение
Иногда мы хотим внедрить реализацию, которую мы не зарегистрировали в контейнере. Это выполнимо с следующим синтаксисом
ручное внедрение в конструктор нового экземпляра TestClass:
container.Bind<ITest1, Test1>().SetToConstructor(new TestClass()) .AsSingle().ActivateNonLazy();
ручное внедрение в проперти нового экземпляра Test3:
container.Bind<ITest1, Test1>().SetToProperty("test",new Test3()).AsSingle().ActivateNonLazy();
container.Bind<ITest1, Test1>().SetToMethod("test",new Test3()) .AsSingle().ActivateNonLazy();
container.SetInstance<ITest1>(Test1).AsSingle().ActivateNonLazy();
Фабрики
Контейнер поддерживает кастомные фабрики, в конструктор фабрики можно внедрить необходимые зависимости из контейнера, по аналогии с обычными зарегистрированными классами, сама фабрика должна наследоваться от BindFactory<T>. В T ConstructObject() мы описываем логику фабрики. Мы можем указать биндинг фабрики явно:
container.SetFactory<Factory2>().ActivateNonLazy();
Ручная очистка
Контейнер можно очистить вручную от всех зависимостей:
container.Dispose();
Updated