2011-11-23 6 views
2

Иногда мы можем сделать некоторые аккуратные трюки с нашим контейнером DI, например: автоматическое связывание, управление одиночными играми, управление одним экземпляром за запрос и т. Д. Это замечательно, и может действительно упростить некоторые сценарии.Предотвращение внедрения деталей реализации в установку контейнера для инъекций зависимостей

Проблема, с которой я сталкиваюсь, заключается в том, что проблемы конкретного класса теперь просачиваются на прикладной уровень. Если класс ожидает, что он будет создан и управляется определенным образом (например, как одиночный или только один раз для HTTP-запроса), теперь он находится на уровне приложения, чтобы обеспечить это.

Некоторые проблемы, которые возникают:

1) потенциальные ошибки, как приложение может некорректно настроить ди привязок.

2) Это может сбивать с толку, когда разработчик хочет реализовать пакет, поскольку правила для настройки контейнера DI не предоставляются самим пакетом, и поэтому вместо этого должны быть документированы в комментариях или сопутствующих тестовых случаях (что не является идеальным).

3) Если реализация класса изменяется, в настоящее время ответственность каждого приложения, использующего класс, обновлять привязки контейнеров DI.

Вот некоторые примеры привязки, которые вы можете сделать с помощью Ninject, что всех выставки этой проблемы:

public class MyApplicationsInjectionModule : NInjectModule 
{ 
    public void Load() 
    { 
     Bind<IFoo>().ToConstant(FooThatShouldBeASingleton.Instant); 

     Bind<IFoo>().To<FooThatShouldBeASingleton>().AsSingleton(); 

     Bind<IFoo>().To<FooThatShouldOnlyBeInstantiatedOncePerRequest>().InRequestScope(); 
    } 
} 

Моего опыт только с Ninject - возможно, некоторые другие контейнеры DI справиться с этой проблемой более элегантно.

Какие стратегии мы можем предпринять, чтобы избежать этих проблем, не отказываясь от мощности, которую предоставляет контейнер DI?

ответ

2

Injection Dependency вводит гибкость, и с этой гибкостью также возникает дополнительный риск неправильного составления графов объектов. Это один из (очень) немногих недостатков DI, и это не имеет никакого отношения к тому, используете ли вы контейнер DI.

1) Потенциальные ошибки, поскольку приложение может неправильно настроить привязки DI.

with Poor Man's DI it's perfectly possible to compose an incorrect object graph.

2) Это может привести к путанице, когда разработчик хочет реализовать пакет, как правила для установки контейнера DI не предусмотрено самой упаковки, и поэтому вместо этого должны быть документированы в комментариях или сопровождающих Test- случаев (что не идеально).

Поэтому лучшая стратегия (на .NET) является принятие конвенции на основе конфигурации. В принципе, вы можете указать контейнеру для сканирования всех соответствующих сборок и регистрации всех открытых классов в отношении интерфейсов, которые они реализуют.

Если вы придерживаетесь Constructor Injection, Авто-проводкой позаботится обо всем остальном для вас.

В качестве примера, давайте предположим, что вы этот класс, определенный в сборке:

public class Foo : IFoo 
{ 
    private readonly IBar bar; 

    public Foo(IBar bar) 
    { 
     if (bar == null) 
      throw new ArgumentNullException("bar"); 

     this.bar = bar; 
    } 

    // Use this.bar for something interesting in the class... 
} 

В другой сборке, вы можете иметь

public class Bar : IBar { } 

контейнер, который выполнен с возможностью сканирования соответствующих узлов найдёте Bar и зарегистрируйте его как IBar, а также найдете Foo и зарегистрировать его против IFoo. Поскольку конструктор Bar статически рекламирует свои требуемые зависимости, Авто-проводка может ударить, и контейнер сможет автоматически разрешить IFoo.

С соответствующими соглашениями на месте вам не нужно перенастраивать контейнер для добавления новых типов в базу кода.

3) Если реализация класса изменяется, в настоящее время ответственность каждого приложения, использующего класс, обновлять привязки контейнеров DI.

Опять же, если вы используете конвенцию по конфигурации, это будет происходить автоматически.

+0

ОК, так что вы в основном говорите: держите это просто - просто не пробуйте ничего сложного. – cbp

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