Лучшее место для Свободной конфигурации IOC/Модулей (в настоящее время пытается Ninject)

Я изо всех сил стараюсь найти наилучшее место для размещения моей конфигурации Ninject "Модули" (место, где указаны привязки типов). Надеюсь, что я просто пропустил какой-то очевидный трюк, так как это начинает превращаться в развязку для меня с использованием свободной конфигурации (и, следовательно, Ninject):

В простой веб-стек, содержащий три отдельных проекта: Web, BusinessLogic, DataAccess. Я не хочу, чтобы веб-уровень должен был напрямую ссылаться на уровень DataAccess, но я не вижу способа обойти это, потому что:

  • Если я поставлю модуль конфигурации DataAccess на уровне DataAccess, мне нужно ссылаться на уровень DataAccess, чтобы я мог получить доступ к модулю конфигурации при создании экземпляра ядра Ninject в уровне веб-сайта

  • Если я поместил модуль конфигурации DataAccess в уровень веб-сайта, мне нужно ссылаться на уровень DataAccess, чтобы получить доступ к типам, которые я хочу связать

  • Если я поместил модуль конфигурации DataAccess в отдельный проект конфигурации, я получаю круговые проблемы с ссылкой при попытке указать привязки для уровней как в Интернете, так и в DataAccess.

    /li >

Часть преимуществ IOC заключается в том, чтобы разрешить свободное соединение, но, насколько я вижу, использование Ninject потребует от меня добавления более прямых ссылок на проекты, которые у меня есть. Что мне не хватает?

Ответ 1

Ninject не требует ссылки на сборки! Вы можете указать Kernel загрузить все модули из сборок, которые соответствуют определенному шаблону - см. Перегрузки Load()! Используя этот механизм, вы можете отобразить свои объекты как модули, как @Daniel Marbach, предлагаемые в том месте, где реализована каждая функция. Мне не нравятся эти огромные модули, определяющие каждую привязку для сборки. Я бы предпочел, чтобы каждый из них в определенном небольшом модуле для определенной функции.

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

Итак, в основном у вас есть:

  • Одна или несколько узлов веб-уровня: содержат контроллеры, представления и привязки для веб-уровня. Каждая из сборок ссылается на некоторые сборки, которые определяют интерфейсы, от которых он зависит.
  • Одна или несколько сборок, которые определяют интерфейсы для зависимостей веб-уровня.
  • Одна или несколько сборок бизнес-логики, реализующих все или некоторые интерфейсы, требуемые веб-уровнем. Ссылка на некоторые сборки, которые содержат интерфейсы объектов, от которых они зависят. Содержит модули, которые определяют привязки для компонентов, которые они предоставляют.
  • Одна или несколько сборок, которые определяют интерфейсы для зависимостей уровня бизнес-логики.
  • Одна или несколько сборок, которые реализуют зависимости уровня бизнес-логики и, возможно, некоторого веб-уровня (например, данные, которые напрямую предоставляются с бизнес-логикой). Содержит модули компонентов, которые они предоставляют.
  • Один загрузочный загрузчик загружает модули этих сборок с помощью kernel.Load("*.dll") или подобных.

Преимущество этого:

  • Нет ссылок от веб-уровня на уровень бизнес-логики и уровень данных
  • Нет ссылки с уровня бизнес-логики на уровень данных
  • Каждый слой может быть заменен без какого-либо воздействия на других.

Ответ 2

Я обычно создаю сборку только для контейнера и конфигурации IOC; Затем эта Ассамблея может ссылаться на все другие сборки и Ninject (или StructureMap в моем случае). Затем веб-приложение просто должно ссылаться на сборку IOC и включать пару строк кода инициализации, которые непосредственно используют сборку IOC.

Однако одно примечание - сборка MyOC не ссылается на веб-сборку (которая вводит циклическую ссылку). Все, что нужно вводить, определяется за пределами веб-сборки, поэтому это меня не беспокоит.

Ответ 3

Лучший способ организовать ваши модули - это функция! Например

  • AuthenticationModule
  • OrderModule
  • CustomerModule

Удачи!

Ответ 4

Я всегда добавлял конфигурацию Ninject Modules в отдельную сборку, такую ​​как Acme.Common, и ссылаюсь на это с Acme.Data, Acme.Domain и т.д., поэтому нет круговых зависимостей, я всегда могу заменить Acme.Common после некоторых изменений в регистрации без проблемы.