如何使用serviceKey匹配parameter.name来解决多个依赖关系?

时间:2020-07-22 19:21:47

标签: dryioc

我试图弄清楚如何让DryIoc解析ExampleClass上的ITest?

这使参数名称与服务密钥匹配,因为有多个注册可以找到正确的服务。

   public class Program
    {
        public void Main()
        {
            var container = new Container();
            
            container.Register<ITest, A>(serviceKey: "a");
            container.Register<ITest, B>(serviceKey: "b");
            container.Register<ExampleClass>();

            var example = container.Resolve<ExampleClass>();
        }
    }
    
    public interface ITest { }
    public class A : ITest { }
    public class B : ITest { }
    public class ExampleClass
    {
        public ExampleClass(ITest a, ITest b)
        {
        }
    }

1 个答案:

答案 0 :(得分:1)

使用Parameters.Of https://www.fuget.org/packages/DryIoc.dll/4.2.5/lib/netstandard2.0/DryIoc.dll/DryIoc/Parameters

public class Program 
{ 
    public void Main() 
    { 
        var c = new Container();
        c.Register<ITest, A>(serviceKey: "a");
        c.Register<ITest, B>(serviceKey: "b");
        c.Register<ExampleClass>(made:
            Made.Of(parameters: Parameters.Of
                .Name("a", serviceKey: "a")
                .Name("b", serviceKey: "b")));
        var example = c.Resolve<ExampleClass>(); 
    }
}

您还可以省略Made.Of(parameters:,因为ParameterSelector返回的Parameters.Of可隐式转换为Made

        c.Register<ExampleClass>(made:
            Parameters.Of
                .Name("a", serviceKey: "a")
                .Name("b", serviceKey: "b"));

您可以在不显式列出参数的情况下将参数名称与参数名称进行更通用的匹配,但是考虑到以后您将添加非键参数,它将更加脆弱:

        c.Register<ExampleClass>(made:
            Parameters.Of.Details(
                (req, parInfo) => ServiceDetails.Of(serviceKey: parInfo.Name)));

另一种类型安全的选项是通过代表其位置参数的委托表达式(Linq.Expressions.Expression<T>)直接指定构造函数-更改构造函数时,此选项将通知您编译错误:

        c.Register<ExampleClass>(made:
            Made.Of(() =>
                new ExampleClass(
                    Arg.Of<ITest>(serviceKey: "a"),
                    Arg.Of<ITest>(serviceKey: "b"))));

上述方法适用于特定注册,但可以在容器级别使用规则进行相同的操作:

var c = new Container(rules =>
    rules.With(parameters:
        Parameters.Of.Details(
            (req, parInfo) => req.ServiceType == typeof(ExampleClass) 
                ? ServiceDetails.Of(serviceKey: parInfo.Name) 
                : null)
));

注意:最后一个选项会影响性能,因为需要检查所有注册的规则。

可以使用相同的方法使用PropertiesAndFields.Of指定属性注入。