Внедрение зависимостей в n-уровневом приложении? - PullRequest
7 голосов
/ 28 января 2009

У меня есть 3-уровневое приложение службы .NET, которое следует стандартному подходу:

Frontend -> Object Model / Business Logic -> Data Access

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

В настоящее время у меня есть класс во внешнем интерфейсе, который настраивает контейнер DI. В основном это большой набор кода, говорящий container.Register<SomeType>() и так далее.

Проблема в том, что он конфигурирует контейнер для всех трех уровней и, следовательно, должен иметь достаточно инвазивные знания об уровне доступа к данным. Наличие кода в моем интерфейсе с такими знаниями вызывает тревожные сигналы в моей голове, так как смысл разделения приложения на уровни состоит в том, чтобы избежать именно такой ситуации.
Это также усугубляется тем фактом, что мой уровень доступа к данным не просто представляет собой SQL-сервер, представляющий собой пустую корзину битов, но состоит из множества сложных COM-взаимодействий и вызовов P / Invoke, что довольно сильно влияет на DI. конфигурации.

Я подумал о том, чтобы разбить его - возможно, иметь один контейнер на уровень или иметь класс «Setup» на каждом уровне, который обращается к глобальному контейнеру DI, чтобы зарегистрировать его собственные биты, но я не уверен, что это вызовет больше проблем, чем решит ...

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

Спасибо, Орион.

1 Ответ

3 голосов
/ 11 февраля 2009

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

С другой стороны, если все слои выполняются в одном и том же процессе, у вас должен быть только один контейнер. Контейнер будет инициализирован и размещен в начальной точке приложения, такой как global.asax для веб-приложения.

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

Kernel.Register(AllTypes.Pick().FromAssemblyName("DataAccessLayer.dll"));
Kernel.Register(AllTypes.Pick().FromAssemblyName("BusinessLogic.dll"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...