I'm currently using Castle Windsor's child container functionality to override the registration of a particular type with a specific instance in a factory method. I am using the child containers purely so that the registration is temporary for a single resolution - in other words, I don't want the registration to affect all resolutions for that type.
Perhaps some code will explain what I mean.
I have a Func which acts as a factory Func<IReportCategory, IReportCategoryViewModel>
- I give it an implementation of an IReportCategory and it returns a new instance of an IReportCategoryViewModel. (IReportCategoryViewModel has a dependency on IReportCategory).
This is registered with Castle Windsor as follows:
container.Register(
Component.For<Func<IReportCategory, IReportCategoryViewModel>>().Instance(
category => ResolveCategoryViewModelFactory(container, category)));
Where ResolveCategoryViewModelFactory
is implemented as follows:
private CategoryViewModel ResolveCategoryViewModelFactory(IWindsorContainer container, IReportCategory category)
{
using (IWindsorContainer childContainer = new WindsorContainer())
{
childContainer.Register(Component.For<IReportCategory>().Instance(category));
container.AddChildContainer(childContainer);
return childContainer.Resolve<IReportCategoryViewModel>();
}
}
What the above method achieves is the resolution of IReportCategoryViewModel, injecting the specific instance of IReportCategory as a dependency. If IReportCategoryViewModel has other dependencies that need satisfying, then these get automatically injected by the container.
I can subsequently use the Func as follows:
public class Test
{
private readonly Func<IReportCategory, IReportCategoryViewModel> factory;
public Test(Func<IReportCategory, IReportCategoryViewModel> factory)
{
this.factory = factory;
}
public void ResolveTest()
{
// Create a category (note: this would probably be resolved from the container in some way)
IReportCategory category = new ReportCategory();
// Call into the factory to resolve the view model
IReportCategoryViewModel vm = factory(category);
}
...
Question: Does this seem like a suitable thing to do? From the impression I get, child containers are not recommended in Castle Windsor - is there another way of achieving the same result?
Thanks for your help.
Following Krzysztof's advice to use Typed Factories, here is how I implemented the above functionality. It is far more simpler than using child containers!
Firstly, create a factory interface which defines the signature of the factory method:
Next, ensure the
TypedFactoryFacility
is enabled in the container:Finally, register the factory interface with the container:
Now you can inject
ICategoryViewModelFactory
into your classes, and call theCreate()
method to create a new instance ofCategoryViewModel
:Warning: The parameter name in the factory method needs to match the parameter name of the constructor of the object the factory creates. In the above example, the factory interface defines the method:
The constructor for
CategoryViewModel
must also have the parameter named "category":This is because the factory method is the equivalent of the following:
Absolutely there are better ways to go, and the code you're using right now has a bug - it will try to release all the component instances you're resolving when you dispose of the child container, therefore they might be unusable (disposed) before you even get a chance to use them.
If I understand your explanation correctly it feels like a job for typed factories.