Циклические ссылки на контейнеры IoC, циклические ссылки на fluent interfaces

#dependency-injection #inversion-of-control #castle-windsor

#внедрение зависимостей #Инверсия контроля #замок-Виндзор

Вопрос:

У меня есть приложение, которое содержит представления, наследуемые от IView (проект A)

У меня есть Windsor IoC Container в качестве синглтона в другом проекте (project B)

Проект A имеет ссылку на проект B и выполняет статический вызов контейнера для разрешения конкретного типа для конкретных представлений

Если я использую конфигурацию XML для настройки своего контейнера, тогда все хорошо.

Если я попытаюсь использовать интерфейс fluent для настройки моего контрайнера, я получу циклическую ссылку, поскольку теперь мне нужно, чтобы проект B ссылался на проект A, чтобы указать интерфейсы и конкретные типы

Итак, каков наилучший способ сделать это с использованием интерфейса fluent?

Редактировать:

Проект A имеет это при запуске приложения :

 IoC.Instance.Start(); // this configures the container from config
IoC.Instance.Container.Resolve<IBootStrapper>().Start();
  

Где IoC — статический класс, определенный в проекте B

Ответ №1:

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

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

Обновить

В комментариях вы объяснили, что ваш проект Project B предназначен исключительно для начальной загрузки IOC. Нет ничего плохого в том, чтобы иметь проект bootstrapper, потому что это позволит вам полностью очистить все остальные проекты от использования любого контейнера IOC. Обычно вы используете проект bootstrapper, если у вас есть несколько библиотек, которые повторно используются несколькими приложениями (например, бизнес-уровень, который используется веб-приложением, веб-службой и службой Windows).

Однако проект bootstrapper должен загружать только «статические» зависимости проектов многократного использования. Нет смысла настраивать вещи, которые меняются для каждого проекта приложения. Далее, поскольку загрузчик сам по себе является проектом многократного использования, вы не хотите, чтобы он зависел от одного из ваших проектов приложений, поскольку это была бы та часть, которую вы будете заменять. Какой смысл иметь ссылку на ASP.NET веб-приложение при запуске службы Windows? Это было бы отвратительно.

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

Другими словами, решение простое: пусть загрузчик загружает зависимости только для проектов ниже, а не для проекта приложения. Однако, если проект приложения является единственным проектом, который у вас есть, вам не нужен проект bootstrapper; он не будет работать.

Комментарии:

1. 1, хотя я бы удалил это «в идеале». Проект B не должен иметь ссылки на контейнер.

2. Вы имеете в виду проект B? Это тот, который, как я сказал, содержит мой контейнер Windsor. Именно там я создаю и настраиваю контейнер … запутался

3. Итак, вы предлагаете просто удалить project B и поместить все в один проект?

4. @Roonooir: Удалите IoC класс из проекта B, потому что вы не должны вызывать IoC.Instance.Container.Resolve непосредственно из проекта B. Смотрите здесь для получения дополнительной информации: bit.ly/a7lU76 .

5. @Roonooir: «вы предлагаете просто удалить проект B». Абсолютно нет. Разделение ваших приложений на уровни по-прежнему является хорошей практикой в моей книге. Нет: убедитесь, что проект B НЕ использует IoC класс или Unity напрямую.