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

UseServiceProviderFactory无法影响HttpContext.RequestServices的问题求助

自定义ServiceProviderFactory仅对根容器生效,无法影响请求作用域容器的问题解决

你通过UseServiceProviderFactory自定义服务提供者工厂后,发现只有app.Services(根服务容器)能正常获取自定义的MyInstance,但HttpContext.RequestServices(请求作用域容器)始终返回null,控制器内也无法正常工作。

问题根源

ASP.NET Core处理每个请求时,会从根容器获取IServiceScopeFactory创建新的请求作用域,再从该作用域中获取请求级的服务提供者(RequestServices)。你的自定义MyServiceProvider虽然重写了GetService,但根容器默认的IServiceScopeFactory在构建时已被内置注册,你的自定义逻辑根本没机会替换它——导致请求作用域使用的还是默认的服务提供者,自然拿不到MyInstance。

解决方案

要让请求作用域也应用自定义逻辑,需要确保自定义的IServiceScopeFactory被正确返回,且其创建的作用域能提供包含自定义逻辑的服务提供者。以下是两种可行的修改方式:

方式1:包装内置ScopeFactory,让作用域使用自定义ServiceProvider

调整自定义的IServiceScopeFactory和IServiceScope实现,包装内置的作用域工厂,确保每个请求作用域都使用你的MyServiceProvider:

class MyServiceScope : IServiceScope
{
    private readonly IServiceProvider _serviceProvider;
    private readonly IDisposable? _innerDisposable;

    public MyServiceScope(IServiceProvider serviceProvider, IDisposable? innerDisposable)
    {
        _serviceProvider = serviceProvider;
        _innerDisposable = innerDisposable;
    }

    public IServiceProvider ServiceProvider => _serviceProvider;

    public void Dispose()
    {
        _innerDisposable?.Dispose();
    }
}

class MyServiceScopeFactory : IServiceScopeFactory
{
    private readonly IServiceScopeFactory _innerScopeFactory;

    public MyServiceScopeFactory(IServiceScopeFactory innerScopeFactory)
    {
        _innerScopeFactory = innerScopeFactory;
    }

    public IServiceScope CreateScope()
    {
        var innerScope = _innerScopeFactory.CreateScope();
        // 用自定义的MyServiceProvider包装作用域内的服务提供者
        return new MyServiceScope(new MyServiceProvider((ServiceProvider)innerScope.ServiceProvider), innerScope);
    }
}

然后修改MyServiceProvider的GetService方法,确保IServiceScopeFactory被正确返回:

class MyServiceProvider : IServiceProvider
{
    private readonly ServiceProvider _services;
    private IServiceScopeFactory? _scopeFactory;

    public MyServiceProvider(ServiceProvider services) => _services = services;

    public object? GetService(Type serviceType)
    {        
        if (serviceType == typeof(MyInstance)) 
            return new MyInstance();
        else if (serviceType == typeof(IServiceScopeFactory))
        {
            if (_scopeFactory == null)
            {
                // 获取内置的ScopeFactory并包装
                var innerFactory = _services.GetService<IServiceScopeFactory>();
                _scopeFactory = new MyServiceScopeFactory(innerFactory!);
            }
            return _scopeFactory;
        }
        else return _services.GetService(serviceType);
    }
}

方式2:在构建阶段直接替换IServiceScopeFactory的注册

更直接的方式是在CreateBuilder阶段替换内置的IServiceScopeFactory注册,这样根容器和所有请求作用域都会使用你的实现:

class MyFactory : IServiceProviderFactory<ContainerBuilder>
{
    public ContainerBuilder CreateBuilder(IServiceCollection services)
    {
        // 替换内置的IServiceScopeFactory单例注册
        services.Replace(ServiceDescriptor.Singleton<IServiceScopeFactory, MyServiceScopeFactory>());
        return new ContainerBuilder(services);
    }

    public IServiceProvider CreateServiceProvider(ContainerBuilder containerBuilder)
    {
        return new MyServiceProvider(containerBuilder.ServiceDescriptors.BuildServiceProvider());
    }
}

修改后,HttpContext.RequestServices和控制器内就能正常获取到MyInstance了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 15:57:17