Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent duplicate registrations - Castle Windsor

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);
}
like image 297
Sam Lad Avatar asked Dec 26 '22 03:12

Sam Lad


2 Answers

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);
    }
}
like image 85
maxlego Avatar answered Dec 29 '22 12:12

maxlego


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.

like image 20
Krzysztof Kozmic Avatar answered Dec 29 '22 11:12

Krzysztof Kozmic