4
votes

sorry if this has been asked before i've tried doing some google-ing and haven't found any matches so here goes....

I have a Castle Windsor container that I add my components to using the following method (where container is an instance of IWindsorContainer)...

container.Register(AllTypes.FromAssemblyNamed("App.Infrastructure")
    .Where(x => !x.IsAbstract && !x.IsInterface)
    .WithService.DefaultInterface()

This works great, however I then want to register another DLL in the same fashion to resolve dependencies from that...

container.Register(AllTypes.FromAssemblyNamed("App.Client.Infrastructure")
    .Where(x => !x.IsAbstract && !x.IsInterface)
    .WithService.DefaultInterface()

Now is there anyway I can get Windsor to notify me if the same interface resolution is being added, ie: only have 1 implementer per interface (take the first if more than one exists).

Hope I have explained myself well enough. I am using Castle Windsor version: 2.5.1.0 and upgrading / changing version is not really an options.


Update:

I've resolved this by removing the duplicate registrations after they have been registered. After the registration is completed I then have a loop below...

var registeredServices = new Dictionary<Type, string>();
foreach (var node in container.Kernel.GraphNodes)
{
    var cmp = ((Castle.Core.ComponentModel)node);
    Type t = cmp.Service;
    if (registeredServices.ContainsKey(t))
        container.Kernel.RemoveComponent(cmp.Name);
    else
        registeredServices.Add(t, cmp.Implementation.FullName);
}
2
it should be default behavior that first registration is resolvedmaxlego
Hi @maxlego. I don't understand what you mean, could you please elaborate on what you mean.Sam Lad
if you register multiple components with the same interface. then when you resolve by this interface you'll get first registered component. As i understand this is what you want. Or is it not?maxlego
Thanks @maxlego, I want it to throw an exception or something similar as we only want one registered component per interface, sorry if I haven't made that clear in my question.Sam Lad

2 Answers

6
votes

i don't know if you can tweak registrars to throw exception, but this simple code snippet might help you

var registeredServices = new List<Type>();

foreach (var node in container.Kernel.GraphNodes)
{
    foreach (var t in ((Castle.Core.ComponentModel)node).Services)
    {
        if (registeredServices.Contains(t))
            throw new Exception(string.Format("service {0} already registered", t));
        registeredServices.Add(t);
    }
}
4
votes

In 2.5 you can, after registering everything, call

var allHandlers = container.Kernel.GetAssingableHandlers(typeof(object));

then you can look at each handler's .Service and find if there are any duplicates, and either throw a helpful exception or something along those lines.

I'd imagine this is something you want to do in a test, not at runtime.