Castle Windsor: автоматическая регистрация типов из одной сборки, реализующих интерфейсы из другой
В качестве контейнера IoC я использую Castle Windsor. У меня есть приложение, которое имеет структуру, похожую на следующую:
- MyApp.Services.dll
IEmployeeService
IContractHoursService
...
- MyApp.ServicesImpl.dll
EmployeeService : MyApp.Services.IEmployeeService
ContractHoursService : MyApp.Services.IContractHoursService
...
В данный момент я использую конфигурацию XML, и каждый раз, когда я добавляю новую пару IService/Service, мне приходится добавлять новый компонент в файл конфигурации XML. Я хочу переключить все это на свободный API регистрации, но пока не выработал правильный рецепт, чтобы делать то, что я хочу.
Кто-нибудь может помочь? Все образы жизни будут singleton
,
Спасибо заранее.
2 ответа
С AllTypes
Вы можете легко сделать это:
Регистрация компонентов по одному может быть очень повторяющейся работой. Также не забывая регистрировать каждый новый тип, который вы добавляете, может быстро привести к разочарованию. К счастью, вам не обязательно делать это, по крайней мере, всегда. Используя класс ввода AllTypes, вы можете выполнять групповую регистрацию типов на основе определенных вами указанных характеристик.
Я думаю, что ваша регистрация будет выглядеть так:
AllTypes.FromAssembly(typeof(EmployeeService).Assembly)
.BasedOn<IEmployeeService>()
.LifeStyle.Singleton
Если вы реализуете базовый тип, как IService
на ваших интерфейсах вы можете зарегистрировать их все сразу, используя следующую конструкцию:
AllTypes.FromAssembly(typeof(EmployeeService).Assembly)
.BasedOn<IService>()
.WithService.FromInterface()
.LifeStyle.Singleton
Дополнительные примеры смотрите в статье. Это очень хорошее описание возможностей.
Я немного поняла ответ Питера (главное, как он предположил, AllTypes
) и придумали это:
// Windsor 2.x
container.Register(
AllTypes.FromAssemblyNamed("MyApp.ServicesImpl")
.Where(type => type.IsPublic)
.WithService.FirstInterface()
);
Это проходит через все публичные занятия в MyApp.ServicesImpl.dll
сборка и регистрирует каждый в контейнере, используя первый интерфейс, который он реализует. Поскольку мне нужны все классы в сборке служб, мне не нужен интерфейс маркера.
Вышесказанное работает для старой версии Windsor. В текущей документации Castle Windsor для регистрации компонентов для последней версии предлагается следующее:
// Windsor latest
container.Register(
AllTypes.FromAssemblyNamed("MyApp.ServicesImpl")
.Where(type => type.IsPublic) // Filtering on public isn't really necessary (see comments) but you could put additional filtering here
.WithService.DefaultInterface()
);