什么是 .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>();
注意:
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 并替换默认容器 —— 但先确认是不是真需要,别一上来就上重武器。
