依赖注入(DI)是实现控制反转(IoC)最常用方式,DI容器负责自动创建对象、解析依赖、管理生命周期;.NET内置Microsoft.Extensions.DependencyInjection为轻量标准生产级容器,手写简易容器有助于理解其注册、解析、缓存三大核心机制及生命周期管理原理。
依赖注入(DI)是实现控制反转(IoC)最常用的方式,而 DI 容器就是负责自动创建对象、解析依赖、管理生命周期的核心组件。在 C# 中,.NET 自带的 Microsoft.Extensions.DependencyInjection 是轻量、标准、生产就绪的 IoC 容器;但要真正理解它,最好先“从零手写一个简易容器”——不是为了替代它,而是看清背后逻辑。
IoC 的本质是“把对象的创建和依赖关系的绑定,从代码内部转移到外部容器来管理”。以前你可能这样写:
var logger = new FileLogger(); var service = new UserService(logger); // 手动传入依赖
这导致类与具体实现强耦合,难测试、难替换。IoC 后,你只声明“我需要一个 ILogger”,容器负责给你合适的实例。
下面是一个仅支持构造函数注入 + 单例/瞬时生命周期的 50 行容器原型,帮你抓住关键脉络:
// 示例:注册与解析 container.Register(LifeTime.Singleton); container.Register (LifeTime.Transient); var service = container.Resolve
(); // 自动注入 ILogger
关键点在于 Resolve 时用反射读取 UserService 构造函数,发现它需要 ILogger,再查注册表,递归构建——这就是“自动装配”的起点。
生产环境直接用 Microsoft.Extensions.DependencyInjection,它已高度优化且与 ASP.NET Core 深度集成:
Microsoft.Extensions.DependencyInjection
var services = new ServiceCollection()
services.AddSingleton() services.AddScoped() services.AddTransient()
var sp = services.BuildServiceProvider();
var logger = sp.GetRequiredService
();
注意:Scoped 在 Web 中通常按 HTTP 请求生命周期管理,需搭配 IServiceScope 使用,避免跨作用域访问。
生命周期不是可选项,而是资源安全的关键:
典型错误:在 Singleton 服务里注入 Scoped 的 DbContext,会导致 DbContext 被长期持有,下次请求拿到的是脏数据或已释放的上下文。
基本上就这些。手写容器帮你拆解原理,.NET 内置容器帮你稳住生产。IoC 不是炫技,而是让类更专注职责、更易替换、更可测试——容器只是让这件事自动化而已。