Using Castle Windsor, I\'d like to create a class that records an integer. But I\'d like to decorate it several times with other classes. I can see how this works if all c
I've found a solution that I believe is the way this should be done. Down in the innards of Windsor the DefaultDependencyResolver
has a method it uses to resolve sub-dependencies (such as a decorated instance of IRecorder
above) called RebuildContextForParameter. It calls this to create a new context to use when resolving the dependency (i.e. the parameter to the constructor). The method is:
/// This method rebuild the context for the parameter type. Naive implementation.
protected virtual CreationContext RebuildContextForParameter(CreationContext current, Type parameterType)
{
if (parameterType.ContainsGenericParameters)
{
return current;
}
return new CreationContext(parameterType, current, false);
}
The false
parameter in CreationContext
constructor is propagateInlineDependencies
, which when true will copy over the current
context's AdditionalArguments
, thereby passing down the parameters to the sub-dependencies.
To flip this false
to true
, create a new class that derives from DefaultDependencyResolver
:
public class DefaultDependencyResolverInheritContext : DefaultDependencyResolver
{
protected override CreationContext RebuildContextForParameter(CreationContext current, Type parameterType)
{
if (parameterType.ContainsGenericParameters)
{
return current;
}
return new CreationContext(parameterType, current, true);
}
}
Then use that when creating the Windsor container:
var kernel = new DefaultKernel(
new DefaultDependencyResolverInheritContext(),
new NotSupportedProxyFactory());
var container = new WindsorContainer(kernel, new DefaultComponentInstaller());
The NotSupportedProxyFactory
and DefaultComponentInstaller
are the defaults when using the parameter-less constructors for DefaultKernel
and WindsorContainer
.
When done, the code above will work when a factory is used to create an IRecorder
, i.e.:
// during type registration/bootstrapping
container.AddFacility();
container.Register(Component.For().ImplementedBy());
container.Register(Component.For().ImplementedBy());
container.Register(Component.For().AsFactory());
Where IRecorderFactory
is:
public interface IRecorderFactory
{
IRecorder Create(int seed);
}
Then this will work as expected:
IRecorderFactory recorderFactory = container.Resolve();
IRecorder recorder = recorderFactory.Create(20);
recorder.Add(6);
Hopefully that helps others!