.net 内置依赖注入容器是 iservicecollection + iserviceprovider,原生支持、无需额外安装,仅提供构造函数注入和 transient/scoped/singleton 生命周期管理。

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










