I am trying to register all classes that implement my IProcess<T1, T2>
interface with Windsor. To accomplish 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 a trying to register is the following:
public class PositionProcesses
: IProcess<CreatePositionParams, PositionDisplayViewModel>,
IProcess<EditPositionParams, PositionDisplayViewModel>
{
}
The first interface gets registered correctly, but upon registering the second interface to be implemented by this class, I am getting 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
on the first loop iteration 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 those are from the VS debugger.
Any ideas?
You should use convention based component registration
BasedOnDescriptor processes = AllTypes.FromAssembly(assemblyWithProcesses)
.BasedOn(typeof (IProcess<,>))
.WithService.AllInterfaces()
.Configure(x => x.LifeStyle.Transient);
container.Register(processes)
EDIT removed first sample as mentioned by @Krzysztof-kozmic
If you have a single component registered for multiple services, I think you'll have to name each registration manually.
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 by the type's full name plus the interface you're registering it for.
精彩评论