This is a fairly straight forward decorator pattern scenario, with the complication that the decorated type has a constructor parameter that is dependent on the type into which
The class design itself seems reasonable. Here's a convention-based container configuration that basically does this:
public class MyConventions : UnityContainerExtension
{
protected override void Initialize()
{
var dependers = from t in typeof(IThing).Assembly.GetExportedTypes()
where t.Name.StartsWith("Depender")
select t;
foreach (var t in dependers)
{
var number = t.Name.TrimStart("Depender".ToArray());
var realName = "Real" + number;
var decoName = "Deco" + number;
var config = "Config" + number;
this.Container.RegisterType(realName,
new InjectionConstructor(config));
this.Container.RegisterType(decoName,
new InjectionConstructor(
new ResolvedParameter(realName)));
this.Container.RegisterType(t,
new InjectionConstructor(
new ResolvedParameter(decoName)));
}
}
}
This configuration will automatically add all classes that match the above predicate, so once you've set it up, you can just add more classes (like Depender4 or Depender5) without revisiting the container configuration at all.
The above configuration satisfies these unit tests:
[Fact]
public void ContainerCorrectlyResolvesDepender1()
{
var container = new UnityContainer().AddNewExtension();
var actual = container.Resolve();
var deco = Assert.IsAssignableFrom(actual.Thing);
var thing = Assert.IsAssignableFrom(deco.Thing);
Assert.Equal("Config1", thing.Configuration);
}
[Fact]
public void ContainerCorrectlyResolvesDepender2()
{
var container = new UnityContainer().AddNewExtension();
var actual = container.Resolve();
var deco = Assert.IsAssignableFrom(actual.Thing);
var thing = Assert.IsAssignableFrom(deco.Thing);
Assert.Equal("Config2", thing.Configuration);
}
[Fact]
public void ContainerCorrectlyResolvesDepender3()
{
var container = new UnityContainer().AddNewExtension();
var actual = container.Resolve();
var deco = Assert.IsAssignableFrom(actual.Thing);
var thing = Assert.IsAssignableFrom(deco.Thing);
Assert.Equal("Config3", thing.Configuration);
}