☰
ASP.NET Core 中的 DI 容器(Dependency Injection Container)实战指南
2026/10/5 6:36:12 网站建设 项目流程
  • 文档
  • 教程
  • 知识库

【免费下载链接】developer-roadmap

Interactive roadmaps, guides and other educational content to help developers grow in their careers.

项目地址:https://gitcode.com/GitHub_Trending/de/developer-roadmap
点击查看免费下载

导读

依赖注入容器(DI Container)是 ASP.NET Core 应用中管理对象创建与生命周期的核心组件,也是依赖注入(Dependency Injection)模式落地的基础设施。本文围绕 roadmaps/aspnet-core/content/di-containers@iM760f8Ys66-VSkMiZfIX.md 的核心定义展开,结合 ASP.NET Core 内置容器、服务生命周期机制以及 Autofac、Scrutor 等常用第三方容器,带你理解容器如何作为"中央注册表"自动解析并注入依赖,掌握AddTransient/AddScoped/AddSingleton三种注册方式的实际用法与选型原则,从而写出低耦合、易测试、可维护的 ASP.NET Core 应用。

什么是 DI 容器

DI 容器是一个框架组件,负责管理应用中对象的实例化(instantiation)与生命周期(lifetime)。它扮演"中央注册表(central registry)"的角色:你在这里声明"哪个具体实现要提供给哪个接口或基类"。

当应用请求某个服务时,容器会自动完成以下工作:

  • 解析依赖:根据注册信息找到目标接口对应的具体实现类型;
  • 注入依赖:把解析出来的实例通过构造函数(或属性)注入到请求方类中;
  • 管理释放:按照注册时声明的服务生命周期,在合适的时机调用IDisposable.Dispose()释放对象。

正是因为这层"注册—解析—注入"的机制,组件之间才得以解耦:类不再需要亲自new出自己依赖的对象,而是只声明"我需要什么",由容器决定"从哪来、何时创建、何时销毁"。

该主题在 ASP.NET Core 技术路线中处于核心位置,与 依赖注入模式、服务生命周期 等知识点紧密关联,也是框架基础能力(ASP.NET Core 基础)中明确列出的核心特性之一。

ASP.NET Core 的内置 DI 容器

ASP.NET Core 把依赖注入直接内建在框架之中,不需要额外安装任何包即可使用。其底层实现是Microsoft.Extensions.DependencyInjection库——一个轻量级容器,负责在应用内创建和管理对象的生命周期。

集中注册:IServiceCollection

容器的一切注册都发生在一个集中的地方:IServiceCollection。最典型的注册入口是Program.cs中的builder.Services:

var builder = WebApplication.CreateBuilder(args); builder.Services.AddScoped<IOrderRepository, OrderRepository>(); builder.Services.AddSingleton<ICacheService, RedisCacheService>(); builder.Services.AddTransient<IEmailSender, SmtpEmailSender>(); var app = builder.Build();

注册完成后,容器会在应用启动时构建出真实的IServiceProvider,后续所有组件的构造请求都由它统一响应。这正是 DI 容器"中央注册表"定位的最直观体现:你在一个位置声明全部依赖关系,剩下的解析与注入交给容器。

注入方式:构造函数注入

ASP.NET Core 默认推荐、也最常用的是构造函数注入。控制器、中间件、服务类都可以直接在构造函数中声明所需依赖,由容器自动提供:

public class OrderController : ControllerBase { private readonly IOrderRepository _repository; private readonly IEmailSender _emailSender; public OrderController( IOrderRepository repository, IEmailSender emailSender) { _repository = repository; _emailSender = emailSender; } }

生命周期:容器如何决定实例的去留

容器管理对象生命周期的方式,是 DI 容器区别于"简单工厂"的关键。ASP.NET Core 提供三种主要生命周期(详见 服务生命周期文档):

生命周期创建时机共享范围适用场景
Transient每次请求服务时都创建新实例不共享轻量、无状态服务
Scoped每个客户端请求(HTTP 请求)内创建一次同一请求内共享一个用户交互内需要保持一致状态的服务(如DbContext)
Singleton首次被请求时创建(或应用启动时)整个应用生命周期共享共享状态、配置、缓存等
Transient:每次都要"新"的

Transient 生命周期 规定:每次从容器请求服务时都生成一个全新实例,即使同一个请求内多次注入也各不相同。它非常适合轻量、无状态的服务,因为对象不跨组件共享,天然避免了共享状态带来的并发问题:

builder.Services.AddTransient<INotificationSender, NotificationSender>();
Scoped:一个请求一个实例

Scoped 生命周期 规定:每个 HTTP 请求内只创建一个实例,处理该请求的所有组件共享同一个实例。这让单个用户交互的全过程数据保持一致,同时又不会把状态泄漏到其他无关请求中。EF Core 的DbContext默认就是 Scoped,这是它能在一次请求内安全共享、跨请求各自独立的原因:

builder.Services.AddScoped<IMyDbContext, MyDbContext>();
Singleton:全程只有一个

Singleton 生命周期 规定:实例在首次被请求(或应用启动)时创建一次,之后整个应用生命周期内所有请求都复用同一个实例。它适合保存共享状态、全局配置或缓存数据的服务:

builder.Services.AddSingleton<IAppCache, AppCache>();

生命周期选型与常见陷阱

  • Singleton 的线程安全要求:单例实例被所有请求并发访问,内部状态必须线程安全;
  • 避免"捕获依赖"(Captive Dependency):不要把一个 Scoped 服务注入到 Singleton 服务中——Singleton 只创建一次,被捕获的 Scoped 实例实际上会退化为 Singleton 语义,引发状态串扰;正确做法是让 Singleton 通过IServiceScopeFactory按需创建作用域;
  • Transient 的轻量原则:如果服务创建成本高(如持有大量资源),Transient 频繁创建会带来性能开销,此时应考虑 Scoped 或 Singleton;
  • Dispose 时机:容器会跟踪它自己创建的实现了IDisposable的实例,并在作用域结束或应用关闭时统一释放。注意:容器不会释放由你自己new出来再注册进容器的对象,这类对象由调用方自行负责清理。

第三方容器:当内置容器不够用时

内置容器(Microsoft.Extensions.DependencyInjection)满足绝大多数场景,但当应用需要更复杂的生命周期管理、程序集扫描或 AOP 式装饰时,可以引入第三方容器(详见 Microsoft.Extensions.DependencyInjection 文档)。

Autofac:成熟的 IoC 容器

Autofac 是 .NET 生态中最流行的 IoC 容器之一,核心能力包括:

  • 在构造函数、属性上自动解析并注入所需服务;
  • 支持复杂的对象生命周期配置(如每依赖、每作用域、每匹配等);
  • 支持程序集扫描批量注册;
  • 通过模块(Module)机制组织大型应用的依赖配置。

典型的接入方式是在Program.cs中用builder.Host.UseServiceProviderFactory替换默认容器工厂,并在ConfigureContainer中编写 Autofac 注册:

var builder = WebApplication.CreateBuilder(args); builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()); builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder => { containerBuilder.RegisterType<OrderService>() .As<IOrderService>() .InstancePerLifetimeScope(); });

Scrutor:给内置容器加装配扫描与装饰

Scrutor 不是替代容器,而是对内置容器的增强扩展,主要带来两个能力:

  1. 程序集扫描注册:按约定或特性自动注册服务,减少手写注册的样板代码:
builder.Services.Scan(scan => scan .FromAssemblyOf<Program>() .AddClasses(classes => classes.AssignableTo<IOrderRepository>()) .AsImplementedInterfaces() .WithScopedLifetime());
  1. 装饰器(Decorator)支持:用干净利落的语法为既有服务叠加横切关注点(如日志、缓存),而无需修改原始实现类:
builder.Services.AddTransient<IOrderService, OrderService>(); builder.Services.Decorate<IOrderService, LoggingOrderService>();

这与 MediatR 通过 pipeline 添加日志、校验、异常处理等行为的思路异曲同工——都是用"不侵入原始实现"的方式扩展行为。

小结

DI 容器是 ASP.NET Core 依赖注入体系的执行引擎,它通过集中注册、自动解析、按生命周期注入与释放,把组件间的耦合降到最低。掌握内置容器的三种生命周期(Transient / Scoped / Singleton)是日常开发的必备技能;当应用复杂度上升时,Autofac 提供更强生命周期控制与模块化组织,Scrutor 则以内置容器为基础补充装配扫描与装饰能力。配合本仓库 ASP.NET Core 路线图,可以继续深入学习 依赖注入模式 与 服务生命周期 的更多细节。

  • 文档
  • 教程
  • 知识库

【免费下载链接】developer-roadmap

Interactive roadmaps, guides and other educational content to help developers grow in their careers.

项目地址:https://gitcode.com/GitHub_Trending/de/developer-roadmap
点击查看免费下载
上一篇:Humanizer IFormatter 接口深度解析:构建多语言本地化格式化器的核心契约
下一篇:树莓派玩家必看:3步解决RetroPie时间重置难题(附硬件时钟改造方案)

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询