Why can't I register one class for multiple interfaces in Windsor?

I am trying to register all classes that implement my IProcess<T1, T2> interface with Windsor. For this, I have the following code in my installer:

  // Register all implemented process interfaces var procTypes = AppDomain.CurrentDomain .GetAssemblies() .SelectMany(x => x.GetTypes()) .Where(x => x.IsDerivedFromOpenGenericType(typeof(IProcess<,>))) .ToList(); foreach (var procType in procTypes) foreach (var procInterface in procType.GetInterfaces().Where(x => x.IsDerivedFromOpenGenericType(typeof(IProcess<,>)))) container.Register(Component.For(procInterface).ImplementedBy(procType).LifeStyle.Transient); 

One of the classes I'm trying to register is as follows:

 public class PositionProcesses : IProcess<CreatePositionParams, PositionDisplayViewModel>, IProcess<EditPositionParams, PositionDisplayViewModel> { } 

The first interface is registered correctly, but after registering the second interface, which will be implemented by this class, I get the following error:

 Test method MyJobLeads.Tests.Controllers.PositionControllerTests.Windsor_Can_Resolve_PositionController_Dependencies threw exception: Castle.MicroKernel.ComponentRegistrationException: There is a component already registered for the given key MyJobLeads.DomainModel.Processes.Positions.PositionProcesses 

in the first iteration of the loop my variables are:

 + procInterface {Name = "IProcess`2" FullName = "MyJobLeads.DomainModel.Data.IProcess`2[[MyJobLeads.DomainModel.ProcessParams.Positions.CreatePositionParams, MyJobLeads.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[MyJobLeads.DomainModel.ViewModels.Positions.PositionDisplayViewModel, MyJobLeads.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"} System.Type {System.RuntimeType} + procType {Name = "PositionProcesses" FullName = "MyJobLeads.DomainModel.Processes.Positions.PositionProcesses"} System.Type {System.RuntimeType} 

on the second:

 + procInterface {Name = "IProcess`2" FullName = "MyJobLeads.DomainModel.Data.IProcess`2[[MyJobLeads.DomainModel.ProcessParams.Positions.EditPositionParams, MyJobLeads.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[MyJobLeads.DomainModel.ViewModels.Positions.PositionDisplayViewModel, MyJobLeads.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"} System.Type {System.RuntimeType} + procType {Name = "PositionProcesses" FullName = "MyJobLeads.DomainModel.Processes.Positions.PositionProcesses"} System.Type {System.RuntimeType} 

(both of them from the VS debugger.

Any ideas?

+4
source share
2 answers

You must use convention-based registration

 BasedOnDescriptor processes = AllTypes.FromAssembly(assemblyWithProcesses) .BasedOn(typeof (IProcess<,>)) .WithService.AllInterfaces() .Configure(x => x.LifeStyle.Transient); container.Register(processes) 

EDIT deleted the first sample mentioned by @ Krzysztof-kozmic

+4
source

If you have one component registered for several services, I think you will have to manually specify each entry.

See: http://docs.castleproject.org/Windsor.Registering-components-by-conventions.ashx#Configuring_registration_13

 container.Register( Component.For(procInterface) .ImplementedBy(procType) .LifeStyle.Transient .Named(component.Implementation.FullName + "-" + procInterface.Name) ); 

This should register each component as a fully qualified name plus the interface for which you register it.

+2
source

Source: https://habr.com/ru/post/1369347/


All Articles