I have an abstract factory (managed by Windsor using .AsFactory()) and one of the components it resolves needs a specific dependency. Normally, this wouldn't be a problem, as Windsor can look at which implementation is registered for that abstraction and supply it. However, there are multiple implementations of that dependency and I want to select one using the same argument as was passed to the top-level factory.
For example:
public interface IAbstractFactory
{
IComponent Create(int argument);
}
public class MyComponent : IComponent
{
public MyComponent(IDependency dependency) { }
}
public interface IDependencyFactory
{
IDependency Create(int argument); // same argument as above
}
I'd like to create the instance of IDependency injected into MyComponent using a Windsor factory with the same argument as was passed into IAbstractFactory. I'd like Windsor to automatically resolve an IDependency using IDependencyFactory and supply it to MyComponent, since I don't want to have to pass the argument into MyComponent when I call it. The specific implementation of IDependency chosen needs to be done based on the same argument passed into IAbstractFactory.Create(argument). This process may need to continue throughout the resolution pipeline, selecting more components using the same argument.
The specific logic to select the implementation will look for the presence of a specific class attribute and attempt to match a value on it, defaulting to Windsor's default selection behavior if it can't be found.
I suspect there's a way to do this using custom handlers or an implementation of ISubDependencyResolver but I'm having trouble fitting the pieces together.
Is there a reasonable way to take care of this just using some of the more advanced registration and component selection features?
Can you explain a bit more about the bigger picture? How do the IComponents or IDependency are being used and by who?
The reason I'm asking for this is as follows:
If the mapping between the int argument and the desired IDependency are known to you in advanced, and it maps for a single IDependency then I'd not add a factory and just directly declare this dependency in the installer:
In the case that a specific component might need more then one IDependency to use so I'd change the MyComponent to depend on the IDependencyFactory itself and the IDependency to declare for which int argument it answers. Something along these lines:
And also implement a ITypedFactoryComoponentSelector that will resolve from the container by the argument intager.
Basically, I'd say you are right about the "Why do I need to implement factories" (or ITypedFactoryComoponentSelector) if you already use the AsFactory - but the TypedFactoryFacility is in its out-of-the-box form for mappings between different object types to different return objects and not different object instances. Maybe read more into the castles documentation about it.
Hope this helps
I've changed the IComponent and IDependency classes to have a DoSomething() function just so I can actually execute something.
Now the MyComponent implementation looks like this:
And I've implemented an ITypedFactoryComponentSelector:
(Should obviously add input validation to check that it has been called for the right factory method)
And then in the installer changed the factory's registration to: