ASP.NET Core无DependencyResolver实现请求级自定义Autofac标记生命周期范围
在ASP.NET Core中实现基于请求的Autofac标记生命周期范围
在ASP.NET Core中,虽然移除了DependencyResolver,但结合Autofac的官方集成和中间件机制,完全可以复现你需要的动态标记生命周期范围功能。核心思路是通过中间件在请求管道中创建自定义标记的Autofac生命周期范围,并让整个请求链路的依赖解析都基于这个范围。
步骤1:完成Autofac与ASP.NET Core的基础集成
首先确保已正确配置Autofac作为ASP.NET Core的服务提供者工厂,保留你原有的服务注册逻辑:
var builder = WebApplication.CreateBuilder(args); // 指定Autofac为服务提供者工厂 builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()); // 配置Autofac容器 builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder => { // 沿用原有的标记生命周期注册逻辑 containerBuilder.RegisterType<Area1Service>().As<IService>().InstancePerMatchingLifetimeScope("Area1"); containerBuilder.RegisterType<Area2Service>().As<IService>().InstancePerMatchingLifetimeScope("Area2"); // 注册控制器、视图组件等ASP.NET Core组件 containerBuilder.RegisterControllersWithViews(); containerBuilder.RegisterViewComponents(); }); var app = builder.Build();
步骤2:编写自定义中间件创建标记生命周期范围
创建中间件,根据请求上下文(如路由区域)生成对应标记的Autofac范围,并替换当前请求的服务提供者:
public class AutofacTaggedScopeMiddleware { private readonly RequestDelegate _next; private readonly IContainer _container; public AutofacTaggedScopeMiddleware(RequestDelegate next, IContainer container) { _next = next; _container = container; } public async Task InvokeAsync(HttpContext context) { // 根据请求获取对应标记(示例从路由区域取值,可替换为自定义逻辑) var areaTag = context.GetRouteValue("area")?.ToString() ?? "Default"; // 统一标记格式,避免大小写或非法值问题 areaTag = areaTag.ToLower() switch { "area1" => "Area1", "area2" => "Area2", _ => "Default" }; // 创建带标记的Autofac生命周期范围 using var scope = _container.BeginLifetimeScope(areaTag); // 替换当前请求的服务提供者为自定义范围的实例 var originalServices = context.RequestServices; context.RequestServices = scope.Resolve<IServiceProvider>(); try { // 执行后续请求管道 await _next(context); } finally { // 恢复原始服务提供者,避免污染后续请求 context.RequestServices = originalServices; } } }
步骤3:注册中间件并保证执行顺序
在Program.cs的管道配置中,将自定义中间件放在路由中间件之前,确保后续所有组件(控制器、视图、过滤器等)都使用自定义范围解析依赖:
// 注册自定义标记范围中间件 app.UseMiddleware<AutofacTaggedScopeMiddleware>(); // 路由中间件需在自定义中间件之后 app.UseRouting(); // 其他管道配置(授权、静态文件等) app.UseAuthorization(); // 配置区域路由 app.MapControllerRoute( name: "areas", pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
核心说明
- 中间件中创建的
LifetimeScope通过using语句自动释放,符合ASP.NET Core请求生命周期的资源管理规则。 - 所有依赖
IService的组件(控制器、视图组件、动作过滤器等)会自动根据当前请求的标记,解析到对应的服务实现。 - 标记的获取逻辑可灵活调整:支持从请求头、查询参数、域名等多种来源提取,适配你实际的业务规则。
内容的提问来源于stack exchange,提问作者Ronny John
相关产品推荐
相关产品推荐

