Castle Windsor: Как я внедряю все реализации интерфейса в ctor?
Я написал интерфейс, который реализуется несколькими классами. Я хочу написать класс Service, который будет иметь все зарегистрированные реализации, введенные в его ctor.
Единственное решение, о котором я могу думать, - это вызвать Service Locator внутри 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();
}
}
}
EDIT. Я должен упомянуть, что я использую Castle Windsor.
Ответы
Ответ 1
Вы должны использовать CollectionResolver
. Проверьте этот Час Чакра Виндзора:
Windsor, по умолчанию, когда вы зависите от IFoo [], IEnumerable или IList проверит, есть ли у вас компонент зарегистрированный для этого точного типа (массив или список IFoo), а не если вы есть какие-либо компоненты, зарегистрированные для IFoo (массив компонентов, не то же, что и компонент, являющийся массивом). Вы можете изменить поведение, чтобы сказать: "Когда вы видите массив или список IFoo, просто дайте мне все IFoos вы можете получить" вы используете CollectionResolver.
Прямая ссылка на Castle Resolvers: Resolvers.
Ответ 2
Я знаю, что это уже ответили, но я подумал, что пример добавления 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>()
);
Ответ 3
Нашел этот ответ полезным, хотя я все еще отсутствовал, как регистрировать все реализации данного интерфейса.
Надеюсь, это поможет!
container.Register(
Classes.FromAssemblyContaining<IVehicle>()
.BasedOn<IVehicle>().WithService.FromInterface()
);
Ответ 4
Ответы все правильные, но я просто хотел добавить немного дополнительной морщинки к нему: вам нужно добавить суб-resolver BEFORE. Вы регистрируете свои компоненты.
Это будет работать:
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));