让 .NET 轻松构建中间件模式代码(二)--- 支持管道的中断和分支

Intro

上次实现了一个基本的构建中间件模式的中间件构建器,现在来丰富一下功能,让它支持中断和分支,分别对应 asp.net core 中的 applicationBuilder.RunapplicationBuilder.MapWhen

实现管道中断

实现中间件的中断其实很简单,通过上一次的分析我们已经知道,中间件每一个部分其实是一个上下文和 next 的委托,只需要忽略 next,不执行 next 就可以了,就可以中断后面中间件的执行。

定义一个 Run 扩展方法来实现方便的实现中间件中断:

public static IPipelineBuilder<TContext> Run<TContext>(this IPipelineBuilder<TContext> builder, Action<TContext> handler)
{
return builder.Use(_ => handler);
} public static IAsyncPipelineBuilder<TContext> Run<TContext>(this IAsyncPipelineBuilder<TContext> builder, Func<TContext, Task> handler)
{
return builder.Use(_ => handler);
}

实现分支

分支的实现主要是参考 asp.net core 里 applicationBuilder.Map/applicationBuilder.MapWhen 实现分支路由的做法,在 asp.net core 里,MapWhen 是一个扩展方法,其实现是一个 MapWhenMiddleware,有兴趣可以看 asp.net core 的源码。

实现原理也挺简单的,其实就是满足分支的条件时创建一个全新的中间件管道,当满足条件的时候就就执行这个分支中间件管道,否则就跳过这个分支进入下一个中间件。

首先在 PipelineBuilder 的接口定义中增加了一个 New 方法用来创建一个全新的中间件管道,定义如下:

public interface IPipelineBuilder<TContext>
{
IPipelineBuilder<TContext> Use(Func<Action<TContext>, Action<TContext>> middleware); Action<TContext> Build(); IPipelineBuilder<TContext> New();
} //
public interface IAsyncPipelineBuilder<TContext>
{
IAsyncPipelineBuilder<TContext> Use(Func<Func<TContext, Task>, Func<TContext, Task>> middleware); Func<TContext, Task> Build(); IAsyncPipelineBuilder<TContext> New();
}

实现就是直接创建了一个新的 PipelineBuilder<TContext> 对象,示例如下:

internal class PipelineBuilder<TContext> : IPipelineBuilder<TContext>
{
private readonly Action<TContext> _completeFunc;
private readonly List<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; for (var i = _pipelines.Count - 1; i >= 0; i--)
{
var pipeline = _pipelines[i];
request = pipeline(request);
} return request;
} public IPipelineBuilder<TContext> New() => new PipelineBuilder<TContext>(_completeFunc);
}

异步的和同步类似,这里就不再赘述,有疑问可以直接看文末的源码链接

接着就可以定义我们的分支扩展了

public static IPipelineBuilder<TContext> When<TContext>(this IPipelineBuilder<TContext> builder, Func<TContext, bool> predict, Action<IPipelineBuilder<TContext>> configureAction)
{
return builder.Use((context, next) =>
{
if (predict.Invoke(context))
{
var branchPipelineBuilder = builder.New();
configureAction(branchPipelineBuilder);
var branchPipeline = branchPipelineBuilder.Build();
branchPipeline.Invoke(context);
}
else
{
next();
}
});
}

使用示例

我们可以使用分支和中断来改造一下昨天的示例,改造完的示例如下:

var requestContext = new RequestContext()
{
RequesterName = "Kangkang",
Hour = 12,
}; var builder = PipelineBuilder.Create<RequestContext>(context =>
{
Console.WriteLine($"{context.RequesterName} {context.Hour}h apply failed");
})
.When(context => context.Hour <= 2, pipeline =>
{
pipeline.Use((context, next) =>
{
Console.WriteLine("This should be invoked");
next();
});
pipeline.Run(context => Console.WriteLine("pass 1"));
pipeline.Use((context, next) =>
{
Console.WriteLine("This should not be invoked");
next();
Console.WriteLine("will this invoke?");
});
})
.When(context => context.Hour <= 4, pipeline =>
{
pipeline.Run(context => Console.WriteLine("pass 2"));
})
.When(context => context.Hour <= 6, pipeline =>
{
pipeline.Run(context => Console.WriteLine("pass 3"));
}) ;
var requestPipeline = builder.Build();
Console.WriteLine();
foreach (var i in Enumerable.Range(1, 8))
{
Console.WriteLine($"--------- h:{i} apply Pipeline------------------");
requestContext.Hour = i;
requestPipeline.Invoke(requestContext);
Console.WriteLine("----------------------------");
}

输出结果如下:

看输出结果我们可以看到 Run 后面注册的中间件是不会执行的,Run 前面注册的中间件正常执行

然后定义的 When 分支也是正确执行的~~

Reference

让 .NET 轻松构建中间件模式代码(二)的更多相关文章

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

    让 .NET 轻松构建中间件模式代码 Intro 在 asp.net core 中中间件的设计令人叹为观止,如此高大上的设计何不集成到自己的代码里呢. 于是就有了封装了一个简单通用的中间件模板的想法, ...

  2. Java工作流引擎-中间件模式代码集成

    关键词:工作流快速开发平台  工作流流设计  业务流程管理   asp.net 开源工作流  bpm工作流系统  java工作流主流框架  自定义工作流引擎 表单设计器  流程设计器 前端代码集成步骤 ...

  3. ASP.NET Core 1.0中的管道-中间件模式

    ASP.NET Core 1.0借鉴了Katana项目的管道设计(Pipeline).日志记录.用户认证.MVC等模块都以中间件(Middleware)的方式注册在管道中.显而易见这样的设计非常松耦合 ...

  4. Core 1.0中的管道-中间件模式

    ASP.NET Core 1.0中的管道-中间件模式 SP.NET Core 1.0借鉴了Katana项目的管道设计(Pipeline).日志记录.用户认证.MVC等模块都以中间件(Middlewar ...

  5. Java设计模式之《构建者模式》及应用场景

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6553374.html 构建者模式,又称建造者模式,将一部负责对象的构建分为许多小对象的构建 ...

  6. 深入浅出的webpack构建工具---DevServer配置项(二)

    深入浅出的webpack构建工具---DevServer配置项(二) 阅读目录 DevServer配置项 1. contentBase 2. port 3. host 4. headers 5. hi ...

  7. 深入探索Java设计模式之构建器模式(五)

    抽丝剥茧 细说架构那些事——[优锐课] 简单的程序不需要大量的设计过程,因为它们只关注有限的解决方案,仅使用几个类.大型程序专注于广泛的设计,该设计比好的设计范例的任何其他属性都更能利用可重用性.宏伟 ...

  8. 前端构建大法 Gulp 系列 (二):为什么选择gulp

    系列目录 前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gul ...

  9. WCF学习之旅—TCP双工模式(二十一)

    WCF学习之旅—请求与答复模式和单向模式(十九) WCF学习之旅—HTTP双工模式(二十) 五.TCP双工模式 上一篇文章中我们学习了HTTP的双工模式,我们今天就学习一下TCP的双工模式. 在一个基 ...

随机推荐

  1. Jenkins分布式构建与并行构建

    Jenkins分布式构建与并行构建 jenkins的架构 Jenkins采用的是"master+agent(slave)"架构.Jenkins master负责提供界面.处理HTT ...

  2. css3笔记系列-3.css中的各种选择器详解,不看后悔系列

    点击上方蓝色字体,关注我 最详细的css3选择器解析 ​ 选择器是什么? 比较官方的解释:在 CSS 中,选择器是一种模式,用于选择需要添加样式的元素. 最常见的 CSS 选择器是元素选择器.换句话说 ...

  3. IOS抓包工具Stream——让移动端的抓包变得轻而易举

    有一天下晚班回家,在地铁上的时候,开发发来信息说,能不能把之前创建的bug再抓包看下数据.顿时心里就想,在地铁上,我上哪抓包去.之后百度了下,发现ios有一款非常实用的抓包工具,大家可以上App St ...

  4. snmap弱口令攻击利用

    科普Snmap: 简单网络管理协议(SNMP) 是专门设计用于在 IP 网络管理网络节点(服务器.工作站.路由器.交换机及HUBS等)的一种标准协议,它是一种应用层协议.具体废话就不多说了,自己百度去 ...

  5. PyCharm导入selenium的webdirver模块出错

    selenium安装好后准备验证一下,导入的webdriver有红色标识,检查了浏览器驱动的.环境变量仍然没有解决问题. 后来在百度找到了原因:项目没安装selenium Interpreter 打开 ...

  6. 用sort 排序

    这两天看了一个比较好的sort总结,所以转载了一下 阅读目录 1.sort 2.sort简介 3.sort扩展 1.sort 使用:#include <algorithm>   using ...

  7. nopcommerce4.0 安装步骤

    前言:近期因工作要求接触nopcommerce,最新版本为4.0,以下所有安装都是基于此版本.接下来我可能会写一系列,为了让自己更好的掌握,也希望能帮助到大家 好记性不如烂笔头,新手也可以避免走我的弯 ...

  8. Hive的数据模型及各模块的应用场景

    Hive的数据模型   Hive数据模型.png 数据模型组成及应用场景 Hive的数据模型主要有:database.table.partition.bucket四部分: 数据模型之database ...

  9. SFDC 401认证准备及考试

    401认证准备及考试 刚过了401的认证,一些个人的体会,希望能帮助到准备过401的朋友. 1. 考试只是手段,不是目的.这个链接的视频请认真看完,http://www.salesforcetrain ...

  10. iOS 项目优化

    前言 iOS性能优化系列篇之"优化总体原则" 不要提前过度优化 要找到性能瓶颈 要在不同性能指标间权衡 要理解优化任务的底层运行机制 要有技术保障体系 一.启动速度优化 1.1 学 ...