UseServiceProviderFactory无法影响HttpContext.RequestServices的问题求助
你通过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

