Предотвращение утечки деталей реализации в настройку Dependency Injection Container - PullRequest
2 голосов
/ 23 ноября 2011

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

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

Некоторые проблемы, которыепроисходят:

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

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?

1 Ответ

2 голосов
/ 23 ноября 2011

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

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

Даже с DI Бедного Человека вполне возможно составить неверный граф объектов .

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

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

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

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

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.

Опять же, если вы используете Convention over Configuration , это произойдет автоматически.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...