Autofac注册类型为自身及指定接口时无法访问具体类型的解决方法
我尝试将程序集类型同时注册为自身及一个指定接口。当添加As<ICustomScreenDef>后,无法再访问具体类型;但使用AsImplementedInterfaces()时,访问具体类型恢复正常。
示例代码:
public class ScreenDef : IScreenDef {} public class MyScreen : ScreenDef, ICustomScreenDef {} public class ScreenGroup { public ScreenGroup(MyScreen myScreen, IEnumerable<ICustomScreenDef> customScreenDefs){} }
注册代码(Program.cs):
builder.RegisterAssemblyTypes(screensAssembly).AssignableTo<IScreenDef>(). OnActivating(e => { IScreenDef screenDef = ((IScreenDef)e.Instance); screenDef.Init(); }) .OnActivated( e => { ... } ).AsSelf().As<ICustomScreenDef>().InstancePerDependency();
使用上述代码时,ScreenGroup无法实例化,因为缺少myScreen依赖;若将AsSelf().As<ICustomScreenDef>()改为AsSelf().AsImplementedInterfaces()则运行正常。请问如何不使用AsImplementedInterfaces()实现需求?
问题出在Autofac的注册逻辑上:当链式调用AsSelf()后再调用As<ICustomScreenDef>(),你没有显式注册IScreenDef服务,同时Autofac的As方法会调整可解析的服务列表,导致MyScreen自身类型的注册未被正确关联。
要解决这个问题,有两种可行方式:
方式一:一次性指定所有服务类型
使用As()的lambda重载,一次性传入所有需要注册的服务类型(自身、ICustomScreenDef、IScreenDef):
builder.RegisterAssemblyTypes(screensAssembly) .AssignableTo<IScreenDef>() .OnActivating(e => { var screenDef = (IScreenDef)e.Instance; screenDef.Init(); }) .OnActivated(e => { ... }) .As(t => new[] { t, typeof(ICustomScreenDef), typeof(IScreenDef) }) .InstancePerDependency();
方式二:显式逐个注册所有服务
依次调用AsSelf()、As<IScreenDef>和As<ICustomScreenDef>,确保所有需要的服务类型都被注册:
builder.RegisterAssemblyTypes(screensAssembly) .AssignableTo<IScreenDef>() .OnActivating(e => { var screenDef = (IScreenDef)e.Instance; screenDef.Init(); }) .OnActivated(e => { ... }) .AsSelf() .As<IScreenDef>() .As<ICustomScreenDef>() .InstancePerDependency();
原代码失效原因
原注册代码只指定了AsSelf()和As<ICustomScreenDef>,但没有显式注册IScreenDef——而你的筛选条件是AssignableTo<IScreenDef>,但该接口并未被加入服务列表。AsImplementedInterfaces()会自动注册所有实现的接口(包括IScreenDef和ICustomScreenDef),同时保留自身类型的注册,所以能正常解析MyScreen和IEnumerable<ICustomScreenDef>。
内容的提问来源于stack exchange,提问作者Filip

