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