I have a component with multiple dependencies:
class Service
{
public Service(IDependencyA a, IDependencyB b, ...) { ... }
}
where some dependencies have single implementation:
class CommonDependencyA : IDependencyA
{
...
}
and some have multiple implementations:
class FooDependencyB : IDependencyB
{
public FooDependencyB(IDependencyC c, ...) { ... }
}
class BarDependencyB : IDependencyB
{
public BarDependencyB(IDependencyC c, ...) { ... }
}
class FooDependencyC : IDependencyC
{
...
}
class BarDependencyC : IDependencyC
{
...
}
Sometimes I want to resolve Service
class using "Bar" implementations, while other times I want "Foo" implementations.
I was thinking about using child container to do the registration. This way I could do something like:
public Service CreateService(IWindsorContainer parent, FooBarType type)
{
using(IWindsorContainer child = SetupChildContainer(parent))
{
if (type == FooBarType.Foo)
{
child.Register(Component.For<IDependencyC>.ImplementedBy<FooDependencyC>().LifeStyle.Transient);
child.Register(Component.For<IDependencyB>.ImplementedBy<FooDependencyB>().LifeStyle.Transient);
...
}
else
{
//register "Bar" implementations
}
child.Register(Component.For<Service>.LifeStyle.Transient);
return child.Resolve<Service>();
}
}
I can then refactor this method into a factory, and register this factory inside the parent container.
What I don't like about this approach is that every time I need to resolve a service, I have to do the registration. I've also read a claim, that using a child container is almost always the wrong solution. So, am I doing it wrong? Is there a better approach? I would rather just register all the components once, then call something like:
var fooService = container.Resolve<Service>(new []{FooBarType.Foo});
and make Widsor figure out the correct dependencies. But I do not know how to do the registration in order for this to work.
I ended up using named dependencies:
container.Register(Component.For<IDependencyA>().ImplementedBy<CommonDependencyA>());
container.Register(Component.For<IDependencyC>().ImplementedBy<FooDependencyC>()
.Named("FooDependencyC"));
container.Register(Component.For<IDependencyB>().ImplementedBy<FooDependencyB>()
.Named("FooDependencyB")
.DependsOn(Dependency.OnComponent(typeof(IDependencyC), "FooDependencyC"));
container.Register(Component.For<Service>().
.Named("FooService")
.DependsOn(Dependency.OnComponent(typeof(IDependencyB), "FooDependencyB"));
Not what I was hoping for (I hate using names), but good enough in my case.