You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

手动解析InstancePerLifetimeScope类型时实例不一致问题求助

问题分析与解决方案

问题根源

你遇到的核心问题是全局ServiceLocator绑定了Autofac根容器,而InstancePerLifetimeScope的实例生命周期是和当前作用域绑定的:

  • 构造注入、actionContext.Request.GetDependencyScope()获取的实例,属于请求级子作用域(根容器下的子作用域,对应单个HTTP请求);
  • 全局ServiceLocator.Current用根容器解析时,会创建根作用域的实例,和请求作用域的实例完全独立,自然是新对象。

解决方法

要让全局ServiceLocator能获取到请求上下文对应的实例,需要让它动态绑定到当前请求的生命周期作用域,而不是固定使用根容器:

  1. 修改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;
}
  1. 确保你已经正确配置了Autofac与Web API的集成(比如注册了AutofacWebApiDependencyResolver),这样请求作用域才会被自动存入HttpContext.Current.Items["AutofacWebRequest"]。

修改后,在HTTP请求上下文内调用ServiceLocator.Current.GetInstance<IUserSettings>(),就能拿到和过滤器、构造注入一致的实例;非请求场景下则会使用根容器的实例。

注意事项

  • 尽量避免使用ServiceLocator模式,它会隐藏依赖关系,导致代码难以测试和维护。如果场景允许,优先使用构造注入。
  • 若必须使用ServiceLocator,务必确保在请求上下文内获取的是当前请求的作用域,否则会出现生命周期不匹配的问题。

内容的提问来源于stack exchange,提问作者Marcin Wasik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 04:27:35