You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Autofac中Register与RegisterType注册方式的行为差异问题

问题分析

你遇到的问题核心是对Autofac的UsingConstructor方法的用法理解有误——它不是用来直接提供构造函数参数值的,而是用来告诉Autofac“我要使用哪个签名的构造函数”,剩下的参数解析工作依然由Autofac容器自动完成。

原因解释

你当前的代码里,给UsingConstructor传递的表达式包含了InjectionConfig.Resolve<...>()调用:

Expression<Func<ClassThatDoesNotWork>> expressionDoesNotWork = () => new ClassThatDoesNotWork(
    new AnotherClass(InjectionConfig.Resolve<RandomInnerClass>()), 
    InjectionConfig.ResolveNamed<WhateverService>("MyServiceType1")
);
builder.RegisterType<ClassThatDoesNotWork>().UsingConstructor(expressionDoesNotWork);

Autofac不会执行这个表达式里的Resolve逻辑,而是会解析这个表达式对应的构造函数签名(也就是ClassThatDoesNotWork(AnotherClass, WhateverService)),然后尝试从容器中直接获取AnotherClass和WhateverService的实例。但你的容器里没有注册AnotherClass,所以Autofac找不到这个依赖,抛出了无法解析参数的异常。

而Register<ClassThatDoesNotWork>(func)的方式之所以能正常工作,是因为你在委托里手动完成了所有依赖的解析和构造函数的调用,完全绕开了Autofac的自动解析逻辑。

解决方案

根据你的需求,有两种正确的处理方式:

方式1:让Autofac自动解析依赖(推荐)

如果你希望Autofac自动处理依赖注入,只需要用UsingConstructor指定构造函数签名(不需要手动Resolve),同时确保所有构造函数依赖的类型都已在容器中注册:

// 先注册AnotherClass(之前你的代码里漏掉了这个关键注册)
builder.RegisterType<AnotherClass>();

// 写法一:直接传递构造函数参数类型,明确指定要使用的构造函数签名
builder.RegisterType<ClassThatDoesNotWork>()
       .UsingConstructor(typeof(AnotherClass), typeof(WhateverService));

// 写法二:用表达式表示构造函数签名(不要带Resolve调用,仅定义参数与构造函数的对应关系)
Expression<Func<AnotherClass, WhateverService, ClassThatDoesNotWork>> ctorExpr = 
    (a, b) => new ClassThatDoesNotWork(a, b);
builder.RegisterType<ClassThatDoesNotWork>().UsingConstructor(ctorExpr);

另外,由于WhateverService是Keyed注册的,如果你需要在解析ClassThatDoesNotWork时指定使用这个Keyed实例,还需要结合WithParameter来明确参数来源:

builder.RegisterType<ClassThatDoesNotWork>()
       .UsingConstructor(typeof(AnotherClass), typeof(WhateverService))
       .WithParameter(
           new ResolvedParameter(
               (pi, ctx) => pi.ParameterType == typeof(WhateverService),
               (pi, ctx) => ctx.ResolveNamed<WhateverService>("MyServiceType1")
           )
       );

方式2:手动控制参数注入(保留委托方式)

如果你确实需要手动控制构造函数的参数创建逻辑,继续使用Register<ClassThatDoesNotWork>(func)的方式是完全没问题的,这里建议改用context.Resolve而非直接调用InjectionConfig.Resolve,能更好地适配Autofac的生命周期管理:

Func<IComponentContext, ClassThatDoesNotWork> funcWorks = context => 
    new ClassThatDoesNotWork(
        new AnotherClass(context.Resolve<RandomInnerClass>()), 
        context.ResolveNamed<WhateverService>("MyServiceType1")
    );
builder.Register<ClassThatDoesNotWork>(funcWorks);
验证修改

按照方式1修改后,ClassThatDoesNotWork就能正常被解析了——Autofac现在能找到所有需要的依赖(AnotherClass已注册,RandomInnerClass和WhateverService也都在容器中有对应的注册项)。

内容的提问来源于stack exchange,提问作者AFract

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:12:22