Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Castle Windsor - how to resolve components based on constructor parameters

Say I have a component like this

public class MyComponent
{
    public MyComponent(string name)
    {
    }
}

I basically want to have the provided constructor parameters behave as part of the component identifier when resolving it. If you've never resolved it with that set of parameters, it will instantiate a new one.

In other words, I want to somehow modify the following test to succeed:

IWindsorContainer container = new WindsorContainer();
container.Register(Component.For<MyComponent>());
MyComponent a1 = container.Resolve<MyComponent>(new { name = "a" });
MyComponent a2 = container.Resolve<MyComponent>(new { name = "a" });
MyComponent b = container.Resolve<MyComponent>(new { name = "b" });

Assert.AreSame(a1, a2);
Assert.AreNotSame(a1, b);

Currently it fails because it will instantiate with name=a, then return the same object for all future name=a and name=b.

Thanks!

like image 464
Cameron Avatar asked Aug 20 '10 13:08

Cameron


1 Answers

Normally this is done at registration-time, not at resolution-time. In fact, calling Resolve() in your code should be rare since you're using the container as a service locator.

container.Register(
   Component.For<MyComponent>()
            .Named("comp_a")
            .DependsOn(new { name = "a" }),
   Component.For<MyComponent>()
            .Named("comp_b")
            .DependsOn(new { name = "b" }));

var a1 = container.Resolve<MyComponent>("comp_a");
var a2 = container.Resolve<MyComponent>("comp_a");
var b = container.Resolve<MyComponent>("comp_b");
Assert.AreSame(a1, a2);
Assert.AreNotSame(a1, b);

Instead of using Resolve() as in my code (which is purely for testing purposes) you normally use service overrides or a handler selector to select which MyComponent to inject into your other services.

like image 127
Mauricio Scheffer Avatar answered Oct 14 '22 21:10

Mauricio Scheffer