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);
}