Castle Windsor: автоматически регистрирует типы из одной сборки, реализующей интерфейсы от другого
Я использую Castle Windsor как мой контейнер IoC. У меня есть приложение, которое имеет структуру, похожую на следующее:
- MyApp.Services.dll
-
IEmployeeService
-
IContractHoursService
-
...
- MyApp.ServicesImpl.dll
-
EmployeeService : MyApp.Services.IEmployeeService
-
ContractHoursService : MyApp.Services.IContractHoursService
-
...
Я использую конфигурацию XML на данный момент, и каждый раз, когда я добавляю новую пару IService/Service, мне нужно добавить новый компонент в файл конфигурации XML. Я хочу переключить все это на свободно регистрирующий API, но не разработал точно правильный рецепт, чтобы делать то, что я хочу.
Может ли кто-нибудь помочь? Стиль жизни будет singleton
.
Большое спасибо заранее.
Ответы
Ответ 1
С помощью AllTypes
вы можете легко сделать это:
Из http://stw.castleproject.org/(S(nppam045y0sdncmbazr1ob55))/Windsor.Registering-components-by-conventions.ashx:
Регистрация компонентов по одному может быть очень повторяющейся. Также помня, что регистрировать каждый новый тип, который вы добавляете, может быстро привести к разочарованию. К счастью, вам не обязательно это делать, по крайней мере, всегда. С помощью класса ввода AllTypes вы можете выполнять групповую регистрацию типов на основе определенных указанных характеристик.
Я думаю, что ваша регистрация будет выглядеть так:
AllTypes.FromAssembly(typeof(EmployeeService).Assembly)
.BasedOn<IEmployeeService>()
.LifeStyle.Singleton
Если вы реализуете базовый тип, например IService
на своих интерфейсах, вы можете зарегистрировать их все сразу, используя следующую конструкцию:
AllTypes.FromAssembly(typeof(EmployeeService).Assembly)
.BasedOn<IService>()
.WithService.FromInterface()
.LifeStyle.Singleton
Дополнительные примеры см. в статье. Это очень хорошее описание возможностей.
Ответ 2
Я принял Pieter answer чуть-чуть (ключ, как он предложил, 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()
);