Я пытаюсь сделать 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>();
Я попробовал несколько вариантов, но я не могу понять, что случилось. Благодарю.
Вы должны зарегистрировать реализации один раз:
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()));
Вы можете сделать это, если вы назовете свои компоненты с помощью 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.
Вы не можете зарегистрировать явно один и тот же компонент (тип) более одного раза.
В соответствии с вашим кодом цикл for приводит к тому, что один и тот же тип (выбранный из массива типов) более одного раза