15

Я изучаю IoC, Injection Dependency и т. Д. И наслаждаюсь процессом. Преимущества развязки и программирования для интерфейсов для меня, без проблем.Как разложить реализацию IoC Framework

Однако мне действительно не нравится привязываться к определенной структуре, например Unity или Autofac или Windsor, потому что я все еще участвую и еще не решил, что лучше для моих целей.

Итак, как я могу обернуть что-то вроде Unity, чтобы я мог легко поменять местами в Виндзоре позднее? (или что-то еще). И вы не смеете сказать, что используйте другой, чтобы ввести первый;)

Спасибо!

R.

P.s. Я пометил Unity, поскольку это мои текущие личные предпочтения (я просто lurve Entlib).

ответ

18

Вы можете попробовать сделать абстракцию из контейнера, объявив IContainer с указанием Resolve и Register. Я сделал это пару раз. Затем вы должны пойти и реализовать контейнер : IContainer и инкапсулировать реальный контейнер IoC своей абстракцией. Я попробовал это с Unity и Castle Windsor.

Но эй, скоро я понял, что это действительно чрезмерное проектирование. Затем я понял, что пытался абстрагироваться от абстракции, но для того, чтобы построить еще одну абстракцию. Это может быть хорошо, чтобы изучить концепцию, но это была настоящая боль в шее в реальном проекте. Я бы настоятельно рекомендовал отказаться от абстракции от контейнера IoC. Если вы правильно используете принцип DI, это будет довольно легко изменить ваш контейнер в любом случае.

Код выглядит усложненной, как

//I did this mess with Service Locator 
var t = ContainerService.Instance.Resolve<IMyType>(); 
//others could go further with same Service Locator 
var t = IoCFactory.Instance.CurrentContainer.Resolve<IMyType>(); 

//better way, use --> IoC and DI <-- 
//when a program starts, or a new instance of the context created 
var t = Container.Resolve<IMyType>() //this lives at the bottom of the stack 
//and then you just pass IMyType to the constructor of other types  
//you don't need to call Resolve again in the logical cycle 

См this post по Ayende.

Да, они абстрагировали инверсию контрольного контейнера. Я думаю, что если вам нужно это сделать, довольно ясно, что вы действительно не понимаете, что такое IoC.

+0

хороший момент, абстрагирование IoC звучит как overdesign – pkmiec

+0

Вы совершенно правы, это для обучения требованиям. Как только я успокоюсь в своем контейнере, я был бы счастлив. Но когда вы учитесь и должны переписывать приложения, чтобы обслуживать другой контейнер, потому что пример в блоге использует x вместо y, ну, через какое-то время он доберется до вас. Я подумал, что было бы неплохо иметь свой собственный пример и просто выяснить способ легко поменять любой контейнер, используемый блоком, чтобы проиллюстрировать конкретную концепцию. – Richard

+0

Согласен, это излишне. У приличного контейнера IoC должно быть достаточно места для конфигурации, чтобы вам не пришлось загрязнять ваш код ссылками на контейнер. Если абстрагирование контейнера является единственным способом заставить его работать, я бы сказал, что вы используете плохой контейнер IoC. – FMM

3

Проверьте библиотеку Common Service Locator.

+6

imho, CSL действительно полезен при создании компонента, который будет использоваться во множестве разрозненных проектов, которые сами могут использовать различные библиотеки IoC. Например, использование CSL в своем единственном бизнес-приложении, например, является излишним. Он значительно упрощает управление зависимостями и предоставляет только очень узкий интерфейс, который может быть просто конкретным в базовой инфраструктуре lib самого приложения. –

+3

Как один из разработчиков CSL, я твердо поддерживаю вышеупомянутый комментарий. CSL предназначен для авторов библиотек, которые хотят контейнер, но не хотят, чтобы выбор библиотеки был выбран в приложении. –

18

Используйте инъекцию конструктора, чтобы сообщить, какие зависимости требуется классу. Каждый контейнер, который вы указали, поддерживает его.

Иногда часть кода не может обеспечить полную независимость контейнера, но эти случаи должны быть очень малой частью вашей кодовой базы.

+5

Абсолютно верно для предпочтительного впрыска конструктора. – FMM

4

Как некоторые другие люди упомянули, предпочитают конструктор инъекции. Это позволит решить многие из ваших проблем.

Если ваши классы имеют прямую зависимость от самого контейнера IoC, он имеет тенденцию быть вариантом использования шаблона локатора службы (anti-). В этом конкретном случае изолируйте типы, которые разрешаются с помощью локатора службы, и отрисуйте это динамическое разрешение с заводским интерфейсом.Так, например, заменить это:

public class Foo 
{ 
    private MyIoCContainer _container; 

    public Foo(MyIoCContainer container) 
    { 
     this._container = container; 
    } 


    public void DoSomething() 
    { 
     // have to do this at runtime for whatever reason 
     var myObj = this._container.Resolve<ISomeType>(); 

     myObj.DoSomething(); 
     myObj.DoSomethingElse(); 
    } 
} 

с этим:

public class Foo 
{ 
    private IObjFactory _provider; 

    public Foo(IObjFactory _provider) 
    { 
     this._provider = provider; 
    } 


    public void DoSomething() 
    { 
     var myObj = _provider.GetObj(); 

     myObj.DoSomething(); 
     myObj.DoSomethingElse(); 
    } 
} 

public interface IObjFactory 
{ 
    ISomeType GetObj(); 
} 

Теперь у вас есть IObjFactory, которые могут инкапсулировать динамическую, во время выполнения характер построения объектов, реализующих ISomeType. Если вы создаете много разных типов объектов из локатора контейнера/службы, то у вас должно быть как минимум столько интерфейсов *Factory (в соответствии с Interface Segregation Principle).

9

Контейнер DI должен использоваться только от Composition Root. Все остальные модули не должны иметь ссылки на контейнер.

-Марк Seemann (автор Dependency Injection in .NET)

Другими словами, если вам нужно изменить только один класс, если вы меняете контейнеры DI.

Впрыск конструктора, как правило, является правильным путем, как и другие. Вы можете вводить фабричные интерфейсы или делегаты Func<T>, если вам нужно создавать объекты «на лету».

Я также предлагаю избегать XML-конфигурации, когда это возможно.

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