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()
    );