ASP.NET Core 3.x中如何在Configure方法获取Autofac的IContainer实例
在ASP.NET Core 3.x中获取Autofac的IContainer实例(用于Configure方法)
你提到的问题很典型——ASP.NET Core 3.x之后,Autofac的集成逻辑确实做了调整,不能再像旧版本那样在ConfigureServices里返回容器适配器,而且自己调用containerBuilder.Build()必然会触发"容器只能构建一次"的异常,因为框架内部会负责最终的容器构建流程。
针对你的需求(在Configure方法中拿到框架构建完成后的IContainer实例),这里有两种可靠的实现方式:
方法一:通过AutofacServiceProvider转换获取容器
ASP.NET Core会用AutofacServiceProvider来封装Autofac容器,你可以在Configure方法中注入IServiceProvider,然后将其转换为Autofac的实现类,进而拿到IContainer:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider) { // 将默认服务提供者转换为Autofac的实现 var autofacProvider = serviceProvider as AutofacServiceProvider; if (autofacProvider != null) { IContainer container = autofacProvider.LifetimeScope.ComponentRegistry.Owner; // 这里就可以用container解析你的Command/Event处理器了 } // 其他中间件配置逻辑... }
这种方式直接复用框架提供的服务实例,不需要额外维护全局变量,代码更简洁规范。
方法二:利用RegisterBuildCallback保存容器引用
如果你觉得类型转换不够直观,也可以在ConfigureContainer中通过注册构建回调的方式,在容器完成构建后保存引用:
private static IContainer _autofacContainer; public void ConfigureContainer(ContainerBuilder builder) { // 正常注册你的服务,比如: builder.RegisterType<OrderCommandHandler>().As<ICommandHandler>(); builder.RegisterType<OrderEventHandler>().As<IEventHandler>(); // 不要自己调用Build()!用注册回调的方式在容器构建完成后保存实例 builder.RegisterBuildCallback(container => { _autofacContainer = container; }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 现在可以直接使用_autofacContainer了 if (_autofacContainer != null) { var handlers = _autofacContainer.Resolve<IEnumerable<ICommandHandler>>(); // 处理你的中间件逻辑... } // 其他中间件配置逻辑... }
RegisterBuildCallback会在框架完成容器构建后触发,完全不会触发重复构建的异常,完美解决了你之前遇到的问题。
额外提醒
虽然你明确知道要避免Service Locator反模式,但还是建议:尽量只在必要的中间件场景下使用容器实例,如果你的中间件可以通过构造函数直接注入所需的处理器集合,优先选择构造注入的方式,这更符合依赖注入的最佳实践。
内容的提问来源于stack exchange,提问作者mbue
相关产品推荐
相关产品推荐

