Castle Windsor: Как я внедряю все реализации интерфейса в ctor? - программирование
Подтвердить что ты не робот

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.

4b9b3361

Ответ 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));