【问题标题】:Autofac. Naming resolving and child dependencies自动法。命名解析和子依赖
【发布时间】:2022-04-04 23:27:47
【问题描述】:

命名/键控解析是否也使用名称解析子依赖项?或者命名解析只对没有子依赖的解析类型应用名称/密钥?

发生错误:

在“ConsoleApplication1.Program+MainClassOne”类型上使用“Autofac.Core.Activators.Reflection.DefaultConstructorFinder”找到的任何构造函数都不能使用可用的服务和参数调用: 无法解析构造函数“Void .ctor(INamed)”的参数“INamed named”。

class Program
{
    static void Main(string[] args)
    {
        var container = new ContainerBuilder();
        container.RegisterType<NamedB>().Named<INamed>("B");
        container.RegisterType<NamedA>().Named<INamed>("A");
        container.RegisterType<MainClassOne>().Named<MainClassOne>("A");
        container.RegisterType<MainClassTwo>().Named<MainClassTwo>("B");

        var di = container.Build();
        var a = di.ResolveNamed<MainClassTwo>("B");
        var a2 = di.ResolveNamed<MainClassOne>("A");

    }

    public class MainClassOne
    {
        public MainClassOne(INamed named)
        {
            Console.WriteLine("MainClassOne= " + named.Name);
        }
    }

    public class MainClassTwo
    {
        public MainClassTwo(INamed named)
        {
            Console.WriteLine("MainClassTwo= " + named.Name);
        }
    }

    public interface INamed
    {
       string Name { get; set; }
    }

    public class NamedA : INamed
    {
        public string Name
        {
            get { return "A"; }
            set { }
        }
    }

    public class NamedB : INamed
    {
        public string Name
        {
            get { return "B"; }
            set { }
        }
    }
}

【问题讨论】:

  • 很遗憾,但似乎只适用于已解决的类型。我检查“WithParameter”及其仅适用于特定类。我认为它的autofac政策。虽然他们可以制作一个参数来传播到子依赖项

标签: c# .net autofac


【解决方案1】:

该密钥仅在解析请求的服务时使用。如果密钥被传递给后续的解析操作,则需要依赖关系图中的所有服务也使用相同的密钥注册。

您想要实现的目标可以使用基于 lambda 的注册来完成,该注册使您的主类的依赖关系显式化。

container.RegisterType<NamedA>().Named<INamed>("A");    
container.RegisterType<NamedB>().Named<INamed>("B");
container.Register(c => new MainClassOne(c.ResolveNamed<INamed>("A"))).Named<MainClassOne>("A");
container.Register(c => new MainClassTwo(c.ResolveNamed<INamed>("B"))).Named<MainClassTwo>("B");

这将允许您使用它们的名称解析主类,同时确保它们也接收正确的命名依赖项。

【讨论】:

  • 最好有一个参数来调节传播。对于我的具体情况,我通过在 LifeTimeScope 中设置它来解决我的问题。感谢您的回答
  • 感谢您的回答亚历克斯。 MainClassOne 和 MainClassTwo 的命名原因是什么? .Named&lt;MainClassOne&gt;("A")。是否有必要或者您只是选择为完全不同的事物使用相同的名称?
【解决方案2】:

将您的注册更新为如下所示:

        container.RegisterType<NamedB>().Named<INamed>("B");
        container.RegisterType<NamedA>().Named<INamed>("A");

        container.RegisterType<MainClassOne>()
            .Named<MainClassOne>("A")
            .WithParameter(
                new ResolvedParameter(
                    (pi, ctx) => pi.Name == "named",
                    (pi, ctx) => ctx.ResolveNamed<INamed>("A")));

        container.RegisterType<MainClassTwo>()
            .Named<MainClassTwo>("B")
            .WithParameter(
                new ResolvedParameter(
                    (pi, ctx) => pi.Name == "named",
                    (pi, ctx) => ctx.ResolveNamed<INamed>("B")));

可能有一些方法可以使这个看起来更整洁(扩展方法等)。另外,请考虑使用 Keyed 而不是 Named 参数。

“ResolvedParameter”类接受两个委托 - 第一个是选择器,允许您确定引用的构造函数参数是否相关,如果是,则执行第二个委托以提供值。

查看keyed servicesselect by context 了解更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-16
    • 2016-10-24
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多