Подтвердить что ты не робот

Почему бы вам не пройти контейнер IoC?

На этой странице "Лучшие практики" AutoFac (http://code.google.com/p/autofac/wiki/BestPractices):

Не пропускайте контейнер вокруг Предоставление компонентам доступа к контейнеру или сохранение его в общедоступном статическом свойстве или создание таких функций, как Resolve(), доступных в глобальном классе "IoC", приводит к поражению цели использования инъекции зависимостей. Такие конструкции имеют больше общего с шаблоном Locator. Если компоненты имеют зависимость от контейнера, посмотрите, как они используют контейнер для извлечения служб, и добавьте эти службы к аргументам конструктора, зависящим от компонента (зависимостям).

Итак, что было бы лучшим способом, чтобы один компонент "динамически" создавал экземпляр другого? В их втором абзаце не рассматривается случай, когда компонент, который "может" быть создан, будет зависеть от состояния системы. Или когда компоненту A необходимо создать X-номер компонента B.

4b9b3361

Ответ 1

Чтобы отвлечься от экземпляра другого компонента, вы можете использовать шаблон Factory:

public interface IComponentBFactory
{
    IComponentB CreateComponentB();
}

public class ComponentA : IComponentA
{
    private IComponentBFactory _componentBFactory;

    public ComponentA(IComponentBFactory componentBFactory)
    {
        _componentBFactory = componentBFactory;
    }

    public void Foo()
    {
        var componentB = _componentBFactory.CreateComponentB();

        ...
    }
}

Затем реализация может быть зарегистрирована в контейнере IoC.

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

Ответ 2

Для этого сценария Autofac имеет определенную функциональность - подробности здесь находятся в wiki: http://code.google.com/p/autofac/wiki/DelegateFactories.

В сущности, если A необходимо создать несколько экземпляров B, A может зависеть от Func <B> и Autofac будет генерировать реализацию, которая возвращает новые Bs из контейнера.

Другие предложения выше, конечно, действительны - подход Autofac имеет несколько отличий:

  • Это позволяет избежать большого количества интерфейсов factory
  • B (продукт factory) все еще может иметь зависимости, введенные контейнером

Надеюсь, это поможет!

Ник

Ответ 3

Шаблоны Service Locator сложнее тестировать, и, конечно, сложнее управлять зависимостями, что может привести к большему сцеплению в вашей системе, чем вы действительно хотите.

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

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

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

Ответ 4

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

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