Вопрос

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

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

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

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

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

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

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

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

Это было полезно?

Решение

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

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

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

Kernel.Register(AllTypes.Pick().FromAssemblyName("DataAccessLayer.dll"));
Kernel.Register(AllTypes.Pick().FromAssemblyName("BusinessLogic.dll"));
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top