news 2026/6/26 5:55:01

解构引擎——依赖注入(DI)与中间件管道

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
解构引擎——依赖注入(DI)与中间件管道

、前言:从“作坊”到“工厂”

在上一篇文章中,我们学会了C#的现代语法,就像掌握了制造精密零件的技术。现在,我们需要把这些零件组装成一台能运转的发动机。

在ASP.NET Core中,有两样东西构成了这台发动机的骨架:依赖注入(DI)中间件

如果你不理解它们,你写的代码可能会变成紧紧缠绕的一团乱麻(我们称之为“面条代码”),难以测试、难以修改。理解了它们,你就掌握了现代Web开发的“设计模式之钥”。

二、灵魂机制:依赖注入(DI)

2.1 为什么要“注入”?——解决紧耦合

假设你需要在一个API中记录日志。最直观的写法可能是直接在代码里new一个对象:

app.MapGet("/bad", () => { var logger = new FileLogger(); // 直接依赖具体的实现类 logger.Log("这是一条日志"); return "日志已记录"; });

这种写法看似简单,实则隐患重重:

  1. 紧耦合:你的API代码死死地绑定了FileLogger。如果哪天老板说“改成存数据库”,你得修改每一处new FileLogger()
  2. 难以测试:做单元测试时,你不想真的去写文件,想用一个假的记录器,但现在你无法替换。

依赖注入的核心思想是:“不要自己new,需要什么向容器要”(控制反转,IoC)。

2.2 服务的三生三世:生命周期

在.NET的DI容器中,注册的服务有三种主要生命周期。这是新手最容易踩坑的地方,请务必理解:

  1. Transient(瞬态)用完即弃。每次请求该服务,容器都会给你一个全新的实例。适合轻量级、无状态的服务(如简单的计算器、格式化工具)。
  2. Scoped(范围)一次请求一生。在一次HTTP请求范围内,无论你在多少个地方请求它,拿到的都是同一个实例。这是Web开发中最常用的模式,特别是用于数据库上下文(DbContext)
  3. Singleton(单例)万世一系。整个应用程序生命周期内,只存在一个实例。适合全局缓存、全局配置。注意:单例服务必须是线程安全的!

2.3 实战:构建一个性能监控服务

我们来写一个真实的案例:统计API的执行耗时。

第一步:定义契约(接口)良好的架构总是面向接口编程。

// IPerformanceTracker.cs public interface IPerformanceTracker { void Start(); void Stop(); long GetElapsedTime(); }

第二步:实现服务

// PerformanceTracker.cs public class PerformanceTracker : IPerformanceTracker { private Stopwatch _stopwatch = new Stopwatch(); public void Start() => _stopwatch.Restart(); public void Stop() => _stopwatch.Stop(); public long GetElapsedTime() => _stopwatch.ElapsedMilliseconds; }

第三步:在Program.cs中注册服务

var builder = WebApplication.CreateBuilder(args); // --- 注册服务 --- // 这里我们使用 Scoped,因为耗时统计通常是针对单个请求的 builder.Services.AddScoped<IPerformanceTracker, PerformanceTracker>(); // 添加Swagger等基础服务 builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // ... 中间件配置 ...

第四步:在API中注入并使用在Minimal API中,我们通过方法参数注入服务。

app.MapGet("/test-performance", (IPerformanceTracker tracker) => { tracker.Start(); // 模拟耗时操作 Thread.Sleep(500); tracker.Stop(); return $"接口执行耗时: {tracker.GetElapsedTime()} ms"; });

架构师视角的深意: 注意看,我们的API代码里完全没有new PerformanceTracker()。这意味着,如果明天我们需要升级监控逻辑(比如加上日志记录),我们只需要修改PerformanceTracker.cs类,而API接口的代码一行都不用动。这就是解耦带来的维护性提升。

三、传动装置:中间件管道

如果说DI是提供动力的气缸,那么中间件就是负责传递动力的齿轮和传送带。

3.1 管道模型:俄罗斯套娃

ASP.NET Core 处理HTTP请求的方式,就像水流通过一系列过滤层。

  1. 请求进入管道。
  2. 经过一个个中间件。
  3. 中间件可以在处理做事(如记录请求日志)。
  4. 中间件调用next()将请求传给下一个中间件。
  5. 到达最终处理逻辑(你的API代码)。
  6. 响应沿着管道反向流出。
  7. 中间件可以在处理做事(如记录响应日志、处理异常)。

3.2 编写你的第一个自定义中间件

我们来写一个最简单的中间件:请求计时器。它将在控制台打印每个请求的耗时。

var app = builder.Build(); // --- 自定义中间件 --- app.Use(async (context, next) => { var stopwatch = new Stopwatch(); stopwatch.Start(); Console.WriteLine($"[中间件] 请求开始: {context.Request.Path}"); // 关键步骤:调用下一个中间件 // 这里使用 await 等待后续管道全部执行完毕 await next(context); stopwatch.Stop(); Console.WriteLine($"[中间件] 请求结束: {context.Request.Path}, 耗时: {stopwatch.ElapsedMilliseconds}ms"); }); // 确保有Swagger中间件 if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.MapGet("/", () => "Hello World!"); app.Run();

运行这段代码,并在浏览器访问http://localhost:5000/,你会看到控制台输出了耗时信息。

3.3 “短路”机制:权限守门员

中间件有一个极其重要的能力:短路。如果中间件决定不调用next(),管道就会直接折返,后续的逻辑(如你的API代码)将不会执行。

这非常适合做权限验证。

app.Use(async (context, next) => { // 模拟:检查Header里是否有密码 if (!context.Request.Headers.ContainsKey("X-Secret-Key")) { // 没有密钥,直接返回401,不调用 next() context.Response.StatusCode = 401; await context.Response.WriteAsync("抱歉,
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 5:51:48

串联、并联电阻计算方法

1、串联分压&#xff0c;计算分压输出。这是电阻分压电路&#xff1a;已知&#xff1a;Vin​24V, R1​10kΩ, R2​3kΩ代入计算Uout​24&#xff08;3➗13&#xff09;​≈ 5.54V问题&#xff1a;为什么不是R1/&#xff08;R1R2&#xff09;?我们先看清节点&#xff1a;上端总…

作者头像 李华
网站建设 2026/6/26 5:50:34

测试硬盘的瑞士军刀-fio

FIO (Flexible I/O Tester) 是一个用于磁盘I/O性能测试的强大工具。它的参数众多&#xff0c;我们不可能也没必要完全记住。下面通过一个具体的命令演示。通过这个具体的例子&#xff0c;希望能帮助你对fio有所了解。 下面命令模拟数据库服务对硬盘的使用&#xff0c;I/O块选择…

作者头像 李华
网站建设 2026/6/26 5:49:43

企业智能表格的机会点在哪?2026 选型与落地实测指南

上周陪一家华东离散制造企业做数字化需求梳理&#xff0c;财务主管拿出一套持续三年的固定工作流程。每到周五关账后&#xff0c;6 名运营、财务人员要从 MES 数据库、ERP 接口导出两份明细&#xff0c;叠加线下巡检 Excel&#xff0c;依靠十多条 VLOOKUP 函数拼接 12 项生产指…

作者头像 李华
网站建设 2026/6/26 5:49:14

中小工厂如何选型?从锟铭智能看设备数据采集关键维度

寻找适合中小工厂的设备数据采集解决方案推荐&#xff1a;回归落地性与实效性面对市场上琳琅满目的工业互联网平台&#xff0c;中小型制造企业在进行数字化转型时往往感到困惑。本文所列内容并非基于商业利益的官方排名&#xff0c;而是依据公开的品牌信息、适用人群特征以及核…

作者头像 李华
网站建设 2026/6/26 5:47:50

除醛喷剂除甲醛的效果、使用频率与用量全解析

除醛喷剂是目前家庭自行治理甲醛时最常用的产品类型。它的核心价值在于能够直接作用于污染源本身——通过喷涂在家具表面、板材接缝等位置&#xff0c;渗透并分解板材浅表层的甲醛&#xff0c;从源头降低释放量。那么&#xff0c;效果到底怎么样&#xff1f;用一次管多久&#…

作者头像 李华
网站建设 2026/6/26 5:46:06

CTF源码解题

1.打开题目发现在页面上没有想要的源码&#xff0c;这就说明flag 写在 HTML 注释 <!-- --> 里&#xff0c;页面肉眼看不到&#xff0c;必须查看网页源代码才能发现。2. 操作步骤&#xff08;浏览器通用&#xff09;步骤 1&#xff1a;打开目标页面访问地址&#xff1a;ht…

作者头像 李华