使用Keyed特性时Autofac 8.0.0误报循环依赖问题排查
Autofac键控注入引发循环依赖的原因与解决
在Autofac 8.0.0中尝试给DummyComboMotor构造函数注入键控(Keyed)的IMotorInterface实例时,抛出循环依赖异常:Circular component dependency detected: DummyComboMotor -> DummyComboMotor -> DummyComboMotor。
复现代码:
using Autofac; using Autofac.Features.AttributeFilters; public interface IMotorInterface { } public class DummyXMotor : IMotorInterface { } public class DummyComboMotor : IMotorInterface { public DummyComboMotor([KeyFilter("XMotor")] IMotorInterface x) {} } class TestClass { static void Main(string[] args) { var builder = new ContainerBuilder(); builder.RegisterType(typeof(DummyXMotor)) .As(typeof(DummyXMotor)) .As(typeof(IMotorInterface)) .Keyed("XMotor", typeof(IMotorInterface)); builder.RegisterType(typeof(DummyComboMotor)) .As(typeof(DummyComboMotor)) .As(typeof(IMotorInterface)) .Keyed("ComboMotor", typeof(IMotorInterface)); var container = builder.Build(); var combo = container.Resolve<DummyComboMotor>(); } }
原因分析
问题核心在于未启用属性过滤支持:
- 你在
DummyComboMotor的构造函数中使用了[KeyFilter]注解,但注册该组件时没有调用WithAttributeFiltering(),导致Autofac完全忽略这个注解,不会按照键控规则解析参数。 - 你先后将
DummyXMotor和DummyComboMotor都注册为默认(无键)的IMotorInterface服务,Autofac中后注册的服务会覆盖前一个,因此默认的IMotorInterface最终指向DummyComboMotor。 - 当Autofac解析
DummyComboMotor的构造函数参数时,会尝试解析默认的IMotorInterface(即DummyComboMotor本身),从而触发循环依赖。
解决方案
在DummyComboMotor的注册代码中添加WithAttributeFiltering(),启用属性过滤支持,让Autofac识别[KeyFilter]注解并按键控规则解析参数。
修改后的完整代码:
using Autofac; using Autofac.Features.AttributeFilters; public interface IMotorInterface { } public class DummyXMotor : IMotorInterface { } public class DummyComboMotor : IMotorInterface { public DummyComboMotor([KeyFilter("XMotor")] IMotorInterface x) {} } class TestClass { static void Main(string[] args) { var builder = new ContainerBuilder(); builder.RegisterType(typeof(DummyXMotor)) .As(typeof(DummyXMotor)) .As(typeof(IMotorInterface)) .Keyed("XMotor", typeof(IMotorInterface)); builder.RegisterType(typeof(DummyComboMotor)) .As(typeof(DummyComboMotor)) .As(typeof(IMotorInterface)) .Keyed("ComboMotor", typeof(IMotorInterface)) .WithAttributeFiltering(); // 新增此行,启用属性过滤 var container = builder.Build(); var combo = container.Resolve<DummyComboMotor>(); } }
额外说明
- 如果不需要
DummyComboMotor作为默认的IMotorInterface服务,可以去掉其注册代码中的.As(typeof(IMotorInterface)),进一步避免默认服务覆盖的问题。 - 若要全局启用属性过滤,可以注册
FilterModule,这样无需为每个组件单独调用WithAttributeFiltering():builder.RegisterModule(new FilterModule());
内容的提问来源于stack exchange,提问作者LogicMan
相关产品推荐
相关产品推荐

