Регистрация того же типа в коллекции с Castle.Windsor дает исключение

1

Я пытаюсь сделать DI с Castle.Windsor компонентами, которые находятся в списке.

У меня есть три типа классов (в этом случае Boats), которые все наследуют от одного интерфейса (IBoat), и я генерирую 10 экземпляров этих типов случайным образом. Когда он добавляет разные типы, все в порядке, но когда дело доходит до добавления того же типа, который уже присутствует в коллекции, он дает следующую ошибку:

Component MarinaTest.SailBoat could not be registered. 
There is already a component with that name. Did you want to modify the existing 
component instead? If not, make sure you specify a unique name.

Родительский класс с коллекцией внутри него выглядит следующим образом:

public class BoatsAtSea
{
    public List<IBoat> BoatsList { get; set; } 
    public BoatsAtSea(List<IBoat> boatsAtSea)
    {
        BoatsList = boatsAtSea;
    }
}

И код замка, который я использую:

Type[] types = {typeof(SailBoat), typeof(FisherBoat), typeof(YachtBoat)};


        var basContainer = new WindsorContainer();
        basContainer.Kernel.Resolver.AddSubResolver(new ListResolver(basContainer.Kernel));
        basContainer.Register(Component.For<BoatsAtSea>());

        // Generate 10 random boats
        for (int i = 0; i < 10; i++)
        {
            basContainer.Register(Component.For<IBoat>().LifestyleTransient().ImplementedBy(types[new Random().Next(3)])
            .DependsOn(Dependency.OnValue("Name", "BT"+ i)));
        }

        BoatsAtSea boats = basContainer.Resolve<BoatsAtSea>();

Я попробовал несколько вариантов, но я не могу понять, что случилось. Благодарю.

Теги:
dependency-injection
castle-windsor

3 ответа

1
Лучший ответ

Вы должны зарегистрировать реализации один раз:

container.Register(Classes.FromThisAssembly()
                          .IncludeNonPublicTypes()
                          .BasedOn<IBoat>()
                          .WithService.FromInterface()
                          .LifestyleTransient());

Затем создайте метод для получения случайной реализации IBoat:

private IEnumerable<IBoat> GetRandomBoatImplementation(IKernel container, int count)
{
    for (int i = 0; i < count; i++)
    {
        yield return container.ResolveAll<IBoat>()
                              .OrderBy(item => Guid.NewGuid())
                              .FirstOrDefault();
    }
}

Используйте этот метод для создания списка. Это делает ListResolver избыточным, потому что мы сами регистрируем тип:

container.Register(Component.For<List<IBoat>>()
                            .UsingFactoryMethod(input => GetRandomBoatImplementation(input, 10).ToList()));
  • 0
    Большое спасибо. Работает как шарм.
0

Вы можете сделать это, если вы назовете свои компоненты с помощью Named:

basContainer.Register(Component.For<IBoat>()
    .LifestyleTransient()
    .ImplementedBy(types[new Random().Next(3)])
    .Named("BT"+i)
    .DependsOn(Dependency.OnValue("Name", "BT"+ i)));

Также вам нужно изменить:

BoatsAtSea(List<IBoat> boatsAtSea)

чтобы:

BoatsAtSea(IList<IBoat> boatsAtSea)

С уважением,

Marwijn.

0

Вы не можете зарегистрировать явно один и тот же компонент (тип) более одного раза.

В соответствии с вашим кодом цикл for приводит к тому, что один и тот же тип (выбранный из массива типов) более одного раза

Ещё вопросы

Сообщество Overcoder
Наверх
Меню