This helpful article from David Haydn (EDIT: scam link removed, it could have been this article) shows how you can use the InjectionConstructor class to help y
While I was waiting for answers on this, I came up with a rather hacky workaround. I've created an extension method on IUnityContainer that lets me register a decorator chain using reflection to create the InjectionConstructor parameters:
static class DecoratorUnityExtensions
{
public static void RegisterDecoratorChain(this IUnityContainer container, Type[] decoratorChain)
{
Type parent = null;
string parentName = null;
foreach (Type t in decoratorChain)
{
string namedInstance = Guid.NewGuid().ToString();
if (parent == null)
{
// top level, just do an ordinary register type
container.RegisterType(typeof(T), t, namedInstance);
}
else
{
// could be cleverer here. Just take first constructor
var constructor = t.GetConstructors()[0];
var resolvedParameters = new List();
foreach (var constructorParam in constructor.GetParameters())
{
if (constructorParam.ParameterType == typeof(T))
{
resolvedParameters.Add(new ResolvedParameter(parentName));
}
else
{
resolvedParameters.Add(new ResolvedParameter(constructorParam.ParameterType));
}
}
if (t == decoratorChain.Last())
{
// not a named instance
container.RegisterType(typeof(T), t, new InjectionConstructor(resolvedParameters.ToArray()));
}
else
{
container.RegisterType(typeof(T), t, namedInstance, new InjectionConstructor(resolvedParameters.ToArray()));
}
}
parent = t;
parentName = namedInstance;
}
}
}
This allows me to configure my container with a much more readable syntax:
[Test]
public void ResolveWithDecorators2()
{
UnityContainer c = new UnityContainer();
c.RegisterInstance(new Mock().Object);
c.RegisterInstance(new Mock().Object);
c.RegisterInstance(new Mock().Object);
c.RegisterDecoratorChain(new Type[] { typeof(ProductRepository), typeof(CachingProductRepository), typeof(LoggingProductRepository) });
Assert.IsInstanceOf(c.Resolve());
}
I'd still be interested to know if there is a more elegant solution to this with Unity