Configuring Unity to resolve a type that takes a decorated dependency that has a parameter that varies with the type into which it is injected

后端 未结 2 1835
清酒与你
清酒与你 2021-02-05 20:15

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

2条回答
  •  悲哀的现实
    2021-02-05 20:52

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

提交回复
热议问题