手动解析InstancePerLifetimeScope类型时实例不一致问题求助
问题分析与解决方案
问题根源
你遇到的核心问题是全局ServiceLocator绑定了Autofac根容器,而InstancePerLifetimeScope的实例生命周期是和当前作用域绑定的:
- 构造注入、
actionContext.Request.GetDependencyScope()获取的实例,属于请求级子作用域(根容器下的子作用域,对应单个HTTP请求); - 全局
ServiceLocator.Current用根容器解析时,会创建根作用域的实例,和请求作用域的实例完全独立,自然是新对象。
解决方法
要让全局ServiceLocator能获取到请求上下文对应的实例,需要让它动态绑定到当前请求的生命周期作用域,而不是固定使用根容器:
- 修改
ServiceLocator.SetLocatorProvider的代码,替换成动态获取当前请求作用域的委托:
private static IContainer BuildContainer() { var builder = new ContainerBuilder(); // 原注册代码保持不变 builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); builder.Register(c => new UserSettings(_connectionString)).As<IUserSettings>().InstancePerLifetimeScope(); var container = builder.Build(); // 替换全局ServiceLocator的提供逻辑 CommonServiceLocator.ServiceLocator.SetLocatorProvider(() => { // 从HttpContext获取当前请求的Autofac作用域(Autofac Web API集成默认会把作用域存在这里) var requestScope = HttpContext.Current?.Items["AutofacWebRequest"] as ILifetimeScope; // 如果不在请求上下文内, fallback到根容器 var targetScope = requestScope ?? container; return new AutofacServiceLocator(targetScope); }); return container; }
- 确保你已经正确配置了Autofac与Web API的集成(比如注册了
AutofacWebApiDependencyResolver),这样请求作用域才会被自动存入HttpContext.Current.Items["AutofacWebRequest"]。
修改后,在HTTP请求上下文内调用ServiceLocator.Current.GetInstance<IUserSettings>(),就能拿到和过滤器、构造注入一致的实例;非请求场景下则会使用根容器的实例。
注意事项
- 尽量避免使用ServiceLocator模式,它会隐藏依赖关系,导致代码难以测试和维护。如果场景允许,优先使用构造注入。
- 若必须使用ServiceLocator,务必确保在请求上下文内获取的是当前请求的作用域,否则会出现生命周期不匹配的问题。
内容的提问来源于stack exchange,提问作者Marcin Wasik
相关产品推荐
相关产品推荐

