让 .NET 轻松构建中间件模式代码

Intro

在 asp.net core 中中间件的设计令人叹为观止,如此高大上的设计何不集成到自己的代码里呢。

于是就有了封装了一个简单通用的中间件模板的想法,以后有需要的时候就可以拿来即用。

接口定义

这里按执行的委托是同步还是异步分为了同步和异步两种构建方法

//没有返回值的同步中间件构建器
public interface IPipelineBuilder<TContext>
{IPipelineBuilder<TContext> Use(Func<Action<TContext>, Action<TContext>> middleware);Action<TContext> Build();
}
// 异步中间件构建器
public interface IAsyncPipelineBuilder<TContext>
{IAsyncPipelineBuilder<TContext> Use(Func<Func<TContext, Task>, Func<TContext, Task>> middleware);Func<TContext, Task> Build();
}

为了方便使用,定义一下扩展方法,使得可以像 asp.net core 中 app.Use(Fun<HttpContext,Func<Task>,Task>) 一样比较方便的使用,扩展方法定义如下:

public static IPipelineBuilder<TContext> Use<TContext>(this IPipelineBuilder<TContext> builder, Action<TContext, Action> action)
{return builder.Use(next =>context =>{action(context, () => next(context));});
}
public static IAsyncPipelineBuilder<TContext> Use<TContext>(this IAsyncPipelineBuilder<TContext> builder,  Func<TContext, Func<Task>, Task> func)
{return builder.Use(next =>context =>{return func(context, () => next(context));});
}

为了方便创建对应的 PipelineBuilder ,这里定义了两个方法:

使用 Create 方法就可以创建一个 IPipelineBuilder ,使用 CreateAsync 就可以创建一个 IAsyncPipelineBuilder

public class PipelineBuilder
{public static IPipelineBuilder<TContext> Create<TContext>(Action<TContext> completeAction){return new PipelineBuilder<TContext>(completeAction);}public static IAsyncPipelineBuilder<TContext> CreateAsync<TContext>(Func<TContext, Task> completeFunc){return new AsyncPipelineBuilder<TContext>(completeFunc);}
}

使用示例

来看一个使用示例,这里的示例修改自设计模式里的责任链模式的一个示例,废话不说,来看代码:

这是一个请假的示例,不同的请假时间交由不同的审批主管进行审批,最后模拟了从请假1小时到请假8小时的申请处理情况

private class RequestContext
{public string RequesterName { get; set; }public int Hour { get; set; }
}
public static void Test()
{var requestContext = new RequestContext(){RequesterName = "Kangkang",Hour = 12,};var builder = PipelineBuilder.Create<RequestContext>(context =>{Console.WriteLine($"{context.RequesterName} {context.Hour}h apply failed");}).Use((context, next) =>{if (context.Hour <= 2){Console.WriteLine("pass 1");}else{next();}}).Use((context, next) =>{if (context.Hour <= 4){Console.WriteLine("pass 2");}else{next();}}).Use((context, next) =>{if (context.Hour <= 6){Console.WriteLine("pass 3");}else{next();}});var requestPipeline = builder.Build();foreach (var i in Enumerable.Range(1, 8)){Console.WriteLine();Console.WriteLine($"--------- h:{i} apply Pipeline------------------");requestContext.Hour = i;requestPipeline.Invoke(requestContext);Console.WriteLine("----------------------------");Console.WriteLine();}
}
public static async Task AsyncPipelineBuilderTest()
{var requestContext = new RequestContext(){RequesterName = "Michael",Hour = 12,};var builder = PipelineBuilder.CreateAsync<RequestContext>(context =>{Console.WriteLine($"{context.RequesterName} {context.Hour}h apply failed");return Task.CompletedTask;}).Use(async (context, next) =>{if (context.Hour <= 2){Console.WriteLine("pass 1");}else{await next();}}).Use(async (context, next) =>{if (context.Hour <= 4){Console.WriteLine("pass 2");}else{await next();}}).Use(async (context, next) =>{if (context.Hour <= 6){Console.WriteLine("pass 3");}else{await next();}});var requestPipeline = builder.Build();foreach (var i in Enumerable.Range(1, 8)){Console.WriteLine($"--------- h:{i} apply AsyncPipeline------------------");requestContext.Hour = i;await requestPipeline.Invoke(requestContext);Console.WriteLine("----------------------------");}
}

运行效果:

实现代码

internal class PipelineBuilder<TContext> : IPipelineBuilder<TContext>
{private readonly Action<TContext> _completeFunc;private readonly IList<Func<Action<TContext>, Action<TContext>>> _pipelines = new List<Func<Action<TContext>, Action<TContext>>>();public PipelineBuilder(Action<TContext> completeFunc){_completeFunc = completeFunc;}public IPipelineBuilder<TContext> Use(Func<Action<TContext>, Action<TContext>> middleware){_pipelines.Add(middleware);return this;}public Action<TContext> Build(){var request = _completeFunc;foreach (var pipeline in _pipelines.Reverse()){request = pipeline(request);}return request;}
}
internal class AsyncPipelineBuilder<TContext> : IAsyncPipelineBuilder<TContext>
{private readonly Func<TContext, Task> _completeFunc;private readonly IList<Func<Func<TContext, Task>, Func<TContext, Task>>> _pipelines = new List<Func<Func<TContext, Task>, Func<TContext, Task>>>();public AsyncPipelineBuilder(Func<TContext, Task> completeFunc){_completeFunc = completeFunc;}public IAsyncPipelineBuilder<TContext> Use(Func<Func<TContext, Task>, Func<TContext, Task>> middleware){_pipelines.Add(middleware);return this;}public Func<TContext, Task> Build(){var request = _completeFunc;foreach (var pipeline in _pipelines.Reverse()){request = pipeline(request);}return request;}
}

Reference

  • https://github.com/WeihanLi/WeihanLi.Common/blob/dev/samples/DotNetCoreSample/PipelineTest.cs

  • https://github.com/WeihanLi/WeihanLi.Common/blob/dev/src/WeihanLi.Common/Helpers/Pipelines/PipelineBuilder.cs

  • https://github.com/dotnet/aspnetcore/blob/master/src/Http/Http/src/Builder/ApplicationBuilder.cs

让 .NET 轻松构建中间件模式代码相关推荐

  1. fusion构建器代码语法_构建器模式:适用于代码,适用于测试

    fusion构建器代码语法 我发现构建器设计模式偶尔在代码中有用,但在测试中经常有用. 本文简要概述了该模式,然后介绍了在测试中使用该模式的一个有效示例. 请参阅github中的代码. 生成器模式的背 ...

  2. 构建器模式:适用于代码,适用于测试

    我发现生成器设计模式偶尔在代码中有用,但在测试中经常有用. 本文简要概述了该模式,然后介绍了在测试中使用该模式的一个有效示例. 请参阅github中的代码. 生成器模式的背景 根据GoF的书 ,构建器 ...

  3. 一行 Python 代码轻松构建树状热力图

    今天和大家一起学习一种可视化技术:构建树状热力图treemap.树形图易于可视化,且易于被人理解.树状图通过展示不同大小的矩形,以传达不同大小的数据量,一般认为,较大的矩形意味着占总体的一大部分,而较 ...

  4. winserver2016 401您无权使用所提供的凭据查看此目录或页面_不用找了,30分钟帮你搞定使用 Spring Cloud 和 Docker 轻松构建微服务架构!...

    点击上方[全栈开发者社区]→右上角[...]→[设为星标⭐] [编者的话]如何使用Spring Boot.Spring Cloud.Docker和Netflix的一些开源工具来构建一个微服务架构.本文 ...

  5. java 构建者模式_Java方法中的参数太多,第3部分:构建器模式

    java 构建者模式 在我的前两篇文章中,我研究了如何通过自定义类型和参数对象减少构造函数或方法调用所需的参数数量. 在本文中,我将讨论如何使用构建器模式来减少构造器所需的参数数量,并讨论该模式如何甚 ...

  6. Java方法中的参数太多,第3部分:构建器模式

    在我的前两篇文章中,我研究了如何通过自定义类型和参数对象减少构造函数或方法调用所需的参数数量. 在本文中,我将讨论如何使用构建器模式来减少构造器所需的参数数量,并讨论该模式如何甚至可以帮助采用过多参数 ...

  7. iis7 您无权使用所提供的凭据查看此目录或页面。_使用 Spring Cloud 和 Docker 轻松构建微服务架构!...

    点击蓝色"架构文摘"关注我哟 加个"星标",每天上午 09:25,干货推送! 原文:https://dzone.com/articles/microservic ...

  8. 11Builder(构建器)模式

    技术交流QQ群:1027579432,欢迎你的加入! 1.Builder(构建器)模式动机 在软件系统中,有时候面临着一个复杂对象的创建工作,其通常由各个部分的子对象用一定的算法构成.由于需求的变化, ...

  9. sql中如何统计各种零件的总数量_如何应用GOF设计模式中的构建者模式创建复合对象实例...

    软件项目实训及课程设计指导--如何应用GOF设计模式中的构建者模式创建复合对象实例 1.GOF设计模式中的构建者模式 构建者设计模式能够将一个复杂对象(它一般为组合类)的构建过程与它的表示部件相互分离 ...

最新文章

  1. C语言 匿名联合体和匿名结构体
  2. 数据库设计范式深入浅出
  3. MongoDB最简单的入门教程之一 环境搭建
  4. sql优化基数和耗费_基数估计在SQL Server优化过程中的位置
  5. 【MATLAB】通信信号调制通用函数 — 带通滤波器
  6. python实现快递地址分拣程序(代码有详细注释)
  7. Building and Securing RESTful APIs in ASP.NET Core 在ASP.NET Core中构建安全的RESTful API Lynda课程中文字幕
  8. Qt基于FFmpeg解码本地视频后再编码
  9. scratch 大家来找茬
  10. 机器人开发--Odoo(OpenERP)
  11. oracle vm win10,virtualbox win10系统下载-oracle vm virtualbox windows 10 64 bitv6.1.14 最新版 - 极光下载站...
  12. pygame实现找方块(色彩敏感度测试)游戏
  13. Unity Toon Shader 卡通着色器(一):卡通着色
  14. java 模拟火车站售票系统_模拟售票系统java编程
  15. 生化危机4(来生/恶灵古堡IV)DVD/700M发布
  16. js正则的test方法一会返回true一会返回false
  17. 鸿蒙系统硬盘分区,电脑硬盘分区分错了有哪些危害?如何正确分区?今天我再说一遍...
  18. 2010年3月30日德国小红伞杀毒登陆中国,你关心吗?
  19. 基于以太坊区块链平台的应用
  20. 容器云系列之Docker容器资源隔离

热门文章

  1. 【啊哈!算法】之二、插入排序
  2. extjs 验证消息不显示
  3. 自定义控件复选框和单选框的实现
  4. [转载MSDN]IIS 7.0中的Live Smooth Streaming -入门
  5. ZGY的Excel特征提取器初期版本完成
  6. java启动mysq服务_Java Web开发——MySQL数据库的安装与配置
  7. CentOS7安装EPEL源
  8. 自动为DEV GridView控件添加SizeChanged事件
  9. 如何像Uber一样给工程师派单,解放外包生产力?
  10. zabbix2.2升级到zabbix3.0.2