C# 管道模式(Pipeline Pattern)详解

发布时间:2026/10/22 20:51:08

C# 管道模式(Pipeline Pattern)详解 C# 管道模式Pipeline Pattern详解一、核心思想你列出的六点本质上是责任链模式 组合模式 依赖注入的组合应用。核心就一句话把流程从一段又长又硬编码的方法拆解成一组可插拔的 Step由管道按顺序编排执行。传统写法 管道写法 DoEverything() Pipeline { ├── Step A stepA(); ├── Step B stepB(); ├── Step C stepC(); └── Step D }二、为什么需要它对比痛点❌ 传统写法的痛点publicclassOrderService{publicvoidPlaceOrder(Orderorder){// 1. 校验if(order.Items.Count0)thrownewException(空订单);// 2. 计算价格order.Totalorder.Items.Sum(ii.Price*i.Qty);// 3. 库存扣减_inventory.Deduct(order);// 4. 支付_payment.Charge(order);// 5. 发通知_email.Send(order);// 6. 记录日志_log.Info(下单成功);// 7. 后续还要加风控、优惠券、积分...}}问题一个方法越来越长可读性差加/删步骤要改这个方法违反开闭原则没法单独测库存扣减这一步难测试其他业务想复用发通知逻辑只能复制粘贴难复用三、核心抽象1. 上下文Context—— 在 Step 之间传递数据publicclassOrderContext{publicOrderOrder{get;set;}new();publicboolIsValid{get;set;}publicdecimalDiscount{get;set;}publicListstringLogs{get;}new();}2. Step 接口 —— 每个步骤只做一件事publicinterfaceIStepTContext{TaskExecuteAsync(TContextcontext,CancellationTokenctdefault);}如果步骤需要决定是否继续往下走可以返回一个结果publicenumStepResult{Continue,Stop}publicinterfaceIStepTContext{TaskStepResultExecuteAsync(TContextcontext,CancellationTokenctdefault);}3. Pipeline —— 负责按顺序编排publicinterfaceIPipelineTContext{TaskExecuteAsync(TContextcontext,CancellationTokenctdefault);}publicclassPipelineTContext:IPipelineTContext{privatereadonlyIEnumerableIStepTContext_steps;publicPipeline(IEnumerableIStepTContextsteps){_stepssteps;}publicasyncTaskExecuteAsync(TContextcontext,CancellationTokenctdefault){foreach(varstepin_steps){varresultawaitstep.ExecuteAsync(context,ct);if(resultStepResult.Stop)break;}}}四、完整示例订单处理管道Step 1 — 校验publicclassValidateOrderStep:IStepOrderContext{publicTaskStepResultExecuteAsync(OrderContextctx,CancellationTokenctdefault){if(ctx.Order.Items.Count0){ctx.IsValidfalse;ctx.Logs.Add(订单为空终止流程);returnTask.FromResult(StepResult.Stop);}ctx.IsValidtrue;ctx.Logs.Add(校验通过);returnTask.FromResult(StepResult.Continue);}}Step 2 — 计算价格publicclassCalculatePriceStep:IStepOrderContext{publicTaskStepResultExecuteAsync(OrderContextctx,CancellationTokenctdefault){ctx.Order.Totalctx.Order.Items.Sum(ii.Price*i.Quantity)-ctx.Discount;ctx.Logs.Add($价格计算完成:{ctx.Order.Total});returnTask.FromResult(StepResult.Continue);}}Step 3 — 扣库存publicclassDeductInventoryStep:IStepOrderContext{privatereadonlyIInventoryService_inventory;publicDeductInventoryStep(IInventoryServiceinventory)_inventoryinventory;publicasyncTaskStepResultExecuteAsync(OrderContextctx,CancellationTokenctdefault){varokawait_inventory.DeductAsync(ctx.Order,ct);if(!ok){ctx.Logs.Add(库存不足终止流程);returnStepResult.Stop;}ctx.Logs.Add(库存扣减成功);returnStepResult.Continue;}}Step 4 — 支付publicclassPaymentStep:IStepOrderContext{privatereadonlyIPaymentService_payment;publicPaymentStep(IPaymentServicepayment)_paymentpayment;publicasyncTaskStepResultExecuteAsync(OrderContextctx,CancellationTokenctdefault){await_payment.ChargeAsync(ctx.Order,ct);ctx.Logs.Add(支付成功);returnStepResult.Continue;}}Step 5 — 通知publicclassNotifyStep:IStepOrderContext{privatereadonlyINotifier_notifier;publicNotifyStep(INotifiernotifier)_notifiernotifier;publicasyncTaskStepResultExecuteAsync(OrderContextctx,CancellationTokenctdefault){await_notifier.SendAsync(ctx.Order,ct);ctx.Logs.Add(通知已发送);returnStepResult.Continue;}}五、编排从硬编码到可配置方式 ADI 容器自动装配推荐// Program.csbuilder.Services.AddScopedIStepOrderContext,ValidateOrderStep();builder.Services.AddScopedIStepOrderContext,CalculatePriceStep();builder.Services.AddScopedIStepOrderContext,DeductInventoryStep();builder.Services.AddScopedIStepOrderContext,PaymentStep();builder.Services.AddScopedIStepOrderContext,NotifyStep();builder.Services.AddScopedIPipelineOrderContext,PipelineOrderContext();调用publicclassOrderAppService{privatereadonlyIPipelineOrderContext_pipeline;publicOrderAppService(IPipelineOrderContextpipeline)_pipelinepipeline;publicasyncTaskPlaceOrderAsync(Orderorder){varctxnewOrderContext{Orderorder};await_pipeline.ExecuteAsync(ctx);}}⚠️IEnumerableIStepT的注入顺序取决于注册顺序。想严格控制顺序看方式 B。方式 B显式命名 排序更可控publicinterfaceIStepTContext{stringName{get;}intOrder{get;}TaskStepResultExecuteAsync(TContextcontext,CancellationTokenctdefault);}在Pipeline中排序_stepssteps.OrderBy(ss.Order).ToList();方式 C从配置/数据库动态生成管道高级// pipeline.json{steps:[ValidateOrderStep,CalculatePriceStep,DeductInventoryStep,PaymentStep,NotifyStep]}publicclassConfigurablePipelineTContext:IPipelineTContext{privatereadonlyIServiceProvider_sp;privatereadonlyListType_stepTypes;publicConfigurablePipeline(IServiceProvidersp,IConfigurationcfg){_spsp;_stepTypescfg.GetSection(pipeline:steps).GetListstring().Select(nType.GetType($MyApp.Steps.{n})!).ToList();}publicasyncTaskExecuteAsync(TContextctx,CancellationTokenctdefault){foreach(vartypein_stepTypes){varstep(IStepTContext)_sp.GetRequiredService(type);if(awaitstep.ExecuteAsync(ctx,ct)StepResult.Stop)break;}}}这样换个 JSON 就换了流程不用重新编译。六、为什么满足你的 6 个特性特性如何满足可读性流程 IEnumerableIStep一眼看清单可维护新增步骤 新增一个类不动老代码可测试每个 Step 都是独立类输入 Context 输出 StepResult直接单测可复用NotifyStep可以同时被订单、退款、注册等管道复用可编排顺序由 DI 注册顺序 / 配置 / 数据库决定SOLID单一职责每 Step 一件事 开闭原则扩展加类修改改配置单测示例xUnitpublicclassValidateOrderStepTests{[Fact]publicasyncTask 空订单_应终止流程(){varstepnewValidateOrderStep();varctxnewOrderContext{OrdernewOrder()};// 无 itemsvarresultawaitstep.ExecuteAsync(ctx);Assert.Equal(StepResult.Stop,result);Assert.False(ctx.IsValid);}[Fact]publicasyncTask 正常订单_应继续(){varstepnewValidateOrderStep();varctxnewOrderContext{OrdernewOrder{Items{newOrderItem{Quantity1}}}};varresultawaitstep.ExecuteAsync(ctx);Assert.Equal(StepResult.Continue,result);Assert.True(ctx.IsValid);}}完全不需要 mock 任何东西。七、进阶中间件风格类似 ASP.NET Core如果 Step 需要包裹下一个 Step做超时、日志、事务可以用洋葱模型publicdelegateTaskStepDelegateTContext(TContextctx);publicinterfaceIMiddlewareTContext{TaskInvokeAsync(TContextctx,StepDelegateTContextnext);}publicclassPipelineBuilderTContext{privatereadonlyListFuncStepDelegateTContext,StepDelegateTContext_componentsnew();publicPipelineBuilderTContextUse(FuncStepDelegateTContext,StepDelegateTContextmiddleware){_components.Add(middleware);returnthis;}publicPipelineBuilderTContextUseStepTS(IServiceProvidersp)whereTS:IStepTContext{returnUse(nextasyncctx{varstepsp.GetRequiredServiceTS();varrawaitstep.ExecuteAsync(ctx);if(rStepResult.Continue)awaitnext(ctx);});}publicStepDelegateTContextBuild(StepDelegateTContextterminal){varappterminal;for(inti_components.Count-1;i0;i--)app_components[i](app);returnapp;}}用法事务 日志 步骤varpipelinenewPipelineBuilderOrderContext().Use(nextasyncctx{usingvartx_db.BeginTransaction();awaitnext(ctx);awaittx.CommitAsync();}).Use(nextasyncctx{varswStopwatch.StartNew();awaitnext(ctx);_log.Info($耗时{sw.ElapsedMilliseconds}ms);}).UseStepValidateOrderStep(sp).UseStepCalculatePriceStep(sp).UseStepPaymentStep(sp).Build(_Task.CompletedTask);awaitpipeline(ctx);八、什么时候不该用步骤永远只有 2~3 个且不会变→ 直接用普通方法别过度设计步骤间强耦合、需要频繁互操作共享局部变量→ 管道反而更绕团队不熟悉这种模式→ 先用注释清晰的顺序方法等复杂了再重构九、总结一句话Pipeline IEnumerableIStepTContext DI 排序 配置驱动。每个 Step 一个类管道负责顺序配置负责编排——这就是可读、可维护、可测试、可复用、可编排、SOLID 的落地方式。需要我针对某个具体业务比如支付回调、审批流、数据 ETL给出更贴合的管道设计吗
延伸阅读

更多相关文章

2026/10/22 20:46:08

深度学习1:基本概念,感知机,激活函数(阶跃,sigmoid,Tanh函数)

建议看尚硅谷深度学习视频一、深度学习基本概念和结构二、感知机和激活函数的由来三、激活函数作用作用一: 没有激活函数,一万层网络也只等于一层线性回归,啥复杂问题都解决不了作用二: 决定神经元是否“放电”(特征过滤)作用三&a…

2026/10/22 22:01:54

DDoS攻击原理与防御实战:从应急到体系构建

1. 从一次实战说起:我为什么开始认真研究DDoS事情要从两年前的一次上线说起。当时某个产品刚做完压测,自认为扛得住一定流量,结果正式对外不到一周,运营同事早上发来消息:“后台监控曲线不对劲,请求量突然翻…

2026/10/22 22:01:54

M-P神经元模型全解析:从生物神经元到深度学习的第一块基石

先说明一下:我写技术分享有个习惯,遇到越是看起来“简单”的概念,越喜欢把它翻来覆去拆透。M-P神经元模型就是典型例子——它在教科书里往往只占两三页,符号简单、公式也不长,看起来像个一次性讲完就能翻篇的入门知识。…

2026/10/22 22:01:54

Opus 5.5 生成视频真相:用大模型写代码,让浏览器逐帧渲染动画

1. 这个标题到底在说什么第一次看到“Opus 5.5 生成视频”这个说法,我差点以为又是一个“输入一句话,直接吐出一段MP4”的模型。实际把玩了一圈才发现,它压根不碰视频编码,也不输出任何视频文件。它做的事情是:根据你的…

2026/10/22 22:01:54

微信小程序投票评选系统源码部署与防刷票实战指南

简介:这是一套面向高校学生与Java初学者、可用于毕业设计或课程实践的微信小程序投票评选系统源码,采用Java后端与微信小程序前端组合,解决从零搭建在线投票、评选与结果统计平台的开发需求。压缩包共884个文件,约19.64MB&#xf…

2026/10/22 21:56:52

Linux下AAC编码实战:FFmpeg编码器选择与参数调优指南

跟音频编码打交道这些年,Linux 上我做得最多的事情之一,就是把各种乱七八糟的音频源转成 AAC。不是因为它有多玄乎,而是在兼容性、压缩比和音质之间,AAC 那个平衡点确实很难被替代。尤其现在流媒体、视频封装、移动端播放器几乎全…

2026/10/22 11:29:28

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/22 0:01:49

电商智能运营体系从0到1:架构设计、落地步骤与避坑指南

前两年我们团队接了一个电商平台的运营中台项目,目标很直白:把过去靠运营拍脑袋做的选品、定价、发券、推活动这些事,逐步用数据算法和自动化流程代替。项目名字内部就叫“电商智能运营体系”。最近有不少朋友问我当时是怎么设计的、踩过哪些…

2026/10/22 0:01:49

若依框架AI代码生成不稳定?用Agent Skill三层结构+五步法搞定

最近一段时间,我一直想把后台管理系统里那些机械重复的增删改查代码交给AI去写。框架用的是若依,按理说这类业务代码模式非常固定,应该是AI最擅长的事情。可真试下来却不是那么回事——你让AI生成一个用户管理模块,它给出的Contro…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑