.NET 内置依赖注入容器是 IServiceCollection + IServiceProvider,原生支持、无需额外安装,仅提供构造函数注入和 Transient/Scoped/Singleton 生命周期管理。
IServiceCollection + IServiceProvider,它不是第三方库(比如 Autofac 或 DryIoc),而是框架原生支持的抽象层。你不需要额外安装包(Microsoft.Extensions.DependencyInjection 在 Microsoft.NET.Sdk 项目中默认引用)。
它的定位是“够用、安全、与 Host 集成好”,不追求高级特性(如属性注入、装饰器、命名注册)。如果你只需要构造函数注入 + 生命周期管理(Transient / Scoped / Singleton),它完全胜任。
IServiceCollection 扩展方法,解析靠 IServiceProvider 的 GetService() 或 GetRequiredService() :
AddTransient() :每次请求都新建实例AddScoped() :每个作用域(如一次 HTTP 请求)内复用同一个实例AddSingleton() :整个应用生命周期只创建一次var services = new ServiceCollection(); services.AddTransient(); services.AddScoped (); services.AddSingleton (); var provider = services.BuildServiceProvider();
// 使用 var userService = provider.GetRequiredService
();
注意:GetService 返回 null 表示未注册;GetRequiredService 抛出
)InvalidOperationException(更推荐,避免空引用)。
IServiceProvider,而应通过 Host.CreateDefaultBuilder() 或 WebApplicationBuilder 注入服务:
var builder = WebApplication.CreateBuilder(args);// 注册服务(自动使用内置容器) builder.Services.AddTransient
(); builder.Services.AddHttpClient (); var app = builder.Build();
原因:
BuildServiceProvider() 会提前触发容器构建,导致中间件、配置、日志等尚未注入HttpContext 绑定 Scoped 服务)InvalidOperationException: A circular dependency was detected。典型场景是 A 依赖 B,B 又依赖 A(包括间接依赖)。
泛型注册要注意闭合类型 vs 开放泛型:
services.AddTransient(typeof(IHandler ✅ 支持开放泛型映射services.AddTransient, OrderCreatedHandler>(); ✅ 显式注册闭合类型services.AddTransient, Handler>() ❌ 编译失败 —— C# 不允许泛型类型参数在泛型方法调用中作为实参直接出现复杂对象图或需要 AOP/装饰器时,内置容器能力很快见顶。这时候才该考虑引入 Autofac 并替换默认容器 —— 但先确认是不是真需要,别一上来就上重武器。