如何在.NET原生依赖注入中创建带额外服务的子作用域
原生.NET依赖注入实现带额外服务的子作用域方案
.NET 原生依赖注入框架的默认实现不支持在已经构建完成的IServiceProvider(包括根容器和普通作用域的ServiceProvider)上动态追加服务注册,要实现类似Autofac的子作用域注册额外服务的能力,不需要注入额外组件,按照以下逻辑实现即可:
核心实现逻辑
- 原生DI的服务注册仅能在
IServiceCollection配置阶段完成,IServiceProvider调用BuildServiceProvider()构建完成后就进入只读状态,没有运行时注册入口。 - 实现带额外服务的子作用域,本质是创建新的
IServiceCollection注册额外服务,将现有父级IServiceProvider设为新服务提供者的父级,构建得到独立的子服务提供者后再创建作用域使用。
代码示例
using Microsoft.Extensions.DependencyInjection; public class DemoService { private readonly IServiceProvider _parentServiceProvider; // 直接注入你当前拿到的IServiceProvider即可,可以是根容器或者父作用域的Provider public DemoService(IServiceProvider parentServiceProvider) { _parentServiceProvider = parentServiceProvider; } public void ExecuteWithChildScope() { // 1. 新建服务集合,注册额外需要的服务 var childServiceCollection = new ServiceCollection(); // 按需求注册自定义服务,支持Singleton/Scoped/Transient生命周期 childServiceCollection.AddScoped<ICustomScopedService, CustomScopedServiceImpl>(); childServiceCollection.AddSingleton<ICustomSingletonService, CustomSingletonServiceImpl>(); // 2. 构建子服务提供者,绑定父Provider,实现父级服务的复用 var childServiceProvider = childServiceCollection.BuildServiceProvider(new ServiceProviderOptions { // 开发环境可开启验证避免作用域问题 ValidateScopes = true, ValidateOnBuild = true }); // 3. 从子Provider创建作用域使用 using var childScope = childServiceProvider.CreateScope(); // 可正常获取子容器注册的额外服务 var customService = childScope.ServiceProvider.GetRequiredService<ICustomScopedService>(); // 也可正常获取父容器/父作用域中注册的服务 var parentService = childScope.ServiceProvider.GetRequiredService<IParentRegisteredService>(); // 执行业务逻辑 } }
注意事项
- 子服务提供者的生命周期完全独立,子容器中注册的Singleton服务仅在子Provider存活时生效,子Provider被GC回收或主动释放后,对应服务也会被释放。
- 如果需要复用父级Scoped作用域内的服务,只需要将父级Scoped作用域的
ServiceProvider作为父Provider传入即可,无需使用根容器Provider。 - 如果有大量频繁动态创建子容器的需求,原生DI的实现性能会略低于Autofac这类支持运行时注册的第三方容器,这种场景也可以考虑接入
Autofac.Extensions.DependencyInjection包,在保留原生DI使用习惯的同时使用Autofac的子容器能力。
内容的提问来源于stack exchange,提问作者t3chb0t
相关产品推荐
相关产品推荐

