Следует ли абстрагировать конфигурацию контейнера IOC от интерфейса пользователя? - PullRequest
0 голосов
/ 07 декабря 2010

Наша команда создала приложение DDD, которое имеет строго определенный уровень обслуживания приложений, который создается как «API» системы.Он обрабатывает все вместе из домена и инфраструктуры для выполнения общих задач.В качестве ввода / вывода он использует только DTO, поэтому домен никогда не будет открыт за пределами этого слоя.

Теперь мы хотим добавить в смесь контейнер внедрения зависимостей, и мы столкнулись с некоторыми трудными выборами.У нас есть два клиентских приложения, которые используют службы приложений для выполнения своей работы: приложение MVC 2 и приложение службы Windows.Традиционно весь код конфигурации для внедрения внедрения зависимостей помещается в файл global.asax в проекте mvc, который я видел в многочисленных примерах.Проблема заключается в том, что регистрационный код IOC затем дублируется в службе Windows и немного изменяется для этой платформы.

У меня проблема в том, что DI требует, чтобы клиентское приложение знало, что регистрировать и как, что также требуетв клиентском приложении есть ссылки на доменный и инфраструктурный уровни.Идея наличия уровня сервисов приложений заключалась в том, что это единственное, что клиенты должны знать и с ними разговаривать.Мое предлагаемое решение состояло в том, чтобы создать «Службу зависимостей» на уровне службы приложений, которую клиенты будут вызывать один раз, и он настроил бы контейнер DI, поскольку он знает, что требуется.У этого также были бы методы, чтобы позволить клиентскому приложению регистрировать дополнительные собственные зависимости.Например, проект MVC зарегистрирует свою фабрику контроллера, а служба Windows зарегистрирует свой класс запуска.Я хотел знать, необычно ли это или я нахожусь на неверном пути с этой идеей.Кто-нибудь еще сталкивался с этой проблемой раньше?

Ответы [ 2 ]

3 голосов
/ 08 декабря 2010

Есть много способов снять шкуру с кошки;похоже, что вы принимаете неправильный подход, однако.Точка входа приложения (Global.asax или Program.cs) обязательно должна быть тем местом, где выбираются компоненты, которые нужно настроить в контейнере IoC.С другой стороны, ваши службы, как правило, не должны иметь каких-либо знаний о конфигурации IoC.Я предполагаю, что вы уже придерживаетесь этого принципа, но пересматриваете его из-за повторяющейся конфигурации.

Чтобы сделать это возможным без повторения кода, как вы описали, многие контейнеры IoC предоставляют конструкции модульности, которые инкапсулируют конфигурациюиз набора связанных компонентов.В Autofac (и Ninject IIRC) они называются «модулями» - http://code.google.com/p/autofac/wiki/StructuringWithModules. Castle Windsor называет их «установщиками», а StructureMap называет их «реестрами».

С учетом конфигурации модулей количествоКод конфигурации в методе запуска приложения уменьшен.В вашем примере для упрощения вы можете создать три модуля:

  • CoreModule
  • WebModule
  • ServiceProcessModule

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

WebModule и ServiceProcessModule будут содержать регистрации для компонентов, специфичных для этих сред, а также специализированную конфигурацию любых общих компонентов, которые настраиваются по-разному в зависимости отthe host.

Тогда запуск вашего веб-приложения будет выглядеть примерно так:

foo.RegisterModule<CoreModule>();
foo.RegisterModule<WebModule>();
// Resolve root component, run app

Хотя процесс обслуживания будет очень похожим, но заменит WebModule для ServiceProcessModule.

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

Надеюсь, это поможет.Ник

2 голосов
/ 07 декабря 2010

Я помещаю класс конфигурации в свой проект DDD или DomainModel и вызываю класс конфигурации в пользовательском интерфейсе.

public static class IoCConfigurator()
{
    public static void Initialize()
    {
        // your code here
    }
}

В вашем пользовательском интерфейсе вы должны вызывать только метод Initialize () и все. Вы можете использовать его в вашем MVC Global.asax и даже в вашем приложении для Windows. Нет дублирования кода.

У меня очень хорошо работает.

...