Castle Windsor: как мне ввести все реализации интерфейса в ctor?
Я написал интерфейс, который реализуется несколькими классами. Я хочу написать класс обслуживания, который будет иметь все зарегистрированные реализации, введенные в его ctor.
единственное решение, которое я могу придумать, - это вызвать локатор служб в ctor и попросить его разрешить() все реализации.
В идеале я хотел бы что-то вроде этого -
interface IVehicle
{
void Start();
}
class Car : IVehicle
{
public void Start()
{
Console.WriteLine("Car started.");
}
}
class Truck : IVehicle
{
public void Start()
{
Console.WriteLine("Truck started.");
}
}
class Motorbike : IVehicle
{
public void Start()
{
Console.WriteLine("Motorbike started.");
}
}
class VehicleService
{
// How do I inject all implementations of IVehicle?
public VehicleService(IEnumerable<IVehicle> vehicles)
{
foreach (var vehicle in vehicles)
{
vehicle.Start();
}
}
}
редактировать - Я должен упомянуть, что я использую замок Виндзор.
4 ответов
вы должны использовать CollectionResolver
. Проверьте это замок Виндзор FAQ:
Windsor, по умолчанию, когда у вас есть зависимость от IFoo[], IEnumerable или IList проверят, есть ли у вас компонент зарегистрирован для этого точного типа (массива или списка IFoo), а не если вы есть ли компоненты, зарегистрированные для IFoo (массив компонентов, не то же самое, что компонент, который является массивом). Вы можете изменить поведение, чтобы сказать: "когда вы видите массив или список IFoo просто дайте мне все IFoos вы можете получить" вы используете CollectionResolver.
прямая ссылка на Castle Resolvers:распознаватели.
Я знаю, что на это уже ответили, но я подумал, что пример того, как добавить CollectionResolver, будет полезен, поэтому вот он.
вызовите AddSubResolver перед регистрацией компонентов в контейнере, например
container = new WindsorContainer();
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));
зарегистрируйте компоненты как обычно:
container.Register(
Component.For<IVehicle>().ImplementedBy<Car>(),
Component.For<IVehicle>().ImplementedBy<Truck>(),
Component.For<IVehicle>().ImplementedBy<Motorbike>()
);
нашел этот ответ полезным, хотя мне все еще не хватало, как зарегистрировать все реализации данного интерфейса.
надеюсь, что это помогает!
container.Register(
Classes.FromAssemblyContaining<IVehicle>()
.BasedOn<IVehicle>().WithService.FromInterface()
);
ответы здесь все правильные, но я просто хотел добавить к нему немного дополнительной морщины: Вы должны добавить суб-решатель до вы регистрируете свои компоненты.
это будет работать:
container = new WindsorContainer();
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));
container.Register(
Component.For<IVehicle>().ImplementedBy<Car>(),
Component.For<IVehicle>().ImplementedBy<Truck>(),
Component.For<IVehicle>().ImplementedBy<Motorbike>()
);
Это не работа
container = new WindsorContainer();
container.Register(
Component.For<IVehicle>().ImplementedBy<Car>(),
Component.For<IVehicle>().ImplementedBy<Truck>(),
Component.For<IVehicle>().ImplementedBy<Motorbike>()
);
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));