Middleware的艺术
定义
Middleware直译叫中间件,目前在百度上很难找到一个简单明了的含义解释,.Net下以前也比较难以看到它的身影,但在Microsoft.Owin里,多个地方都看到MiddleWare,我近来在尝试理解Middleware,并在实际中模仿应用,本文章将我的个人理解和大家分享一下。
Middleware的抽象
Microsoft.Owin的Middleware
public abstract class OwinMiddleware
{
protected OwinMiddleware(OwinMiddleware next); protected OwinMiddleware Next { get; set; } public abstract Task Invoke(IOwinContext context);
}
微软把Middleware定义在抽象类,除了Invoke的中间件执行入口,还有一个Next的中间件属性,两者都是非常抽象。Invoke正是本中间件的处理逻辑,参数IOwinContext包含问题试卷和答题卡,Next表示下一个中间件,如果本中间件不想解决此问题,那么就让Next来解决这个问题,以此类推。提问题的人不用关注是谁回答了问题,他只关注答案了够了。
简单的Middleware接口
如果我们把中间件定义为接口,那么一个简单的中间件接口可以如下:
public interface IMiddleware
{
IMiddleware Next { set; }
Answer GetAnswer(Question question);
}
当然,在一些实际项目中,中间件的抽象程度不一样,所以中间件的执行方法是根据实际需要作合理的设计,但Next一般不会有变化,它都是代表下一个中间件。
Middleware和插件的区别
插件是应用程序的功能扩展,它可以只关注自身的功能的实现,它可能不是带问题的,但各插件的执行接口是一样的,最简单的插件接口可以如下:
public interface IPlug
{
// 加载执行插件
void Init();
}
Middleware是问题解决单元抽象,它往往是由多个单元同时协同工作,各单元虽然没有直接关系,但Next属性还是得到了下个中间件的实例,提供给本中间件来传递。Middlware随着数量的增多,解决的问题各类也可以越多,和插件越多功能越丰富有相似。
Middleware的使用场景
我曾经写过《.Net下一个类型转换神器》,近期在代码重构,发现这玩意很适合使用中间件来实现。在类型转换中,调用者想要的是这种:
/// <summary>
/// 将value转换为目标类型
/// </summary>
/// <param name="value">要转换的值</param>
/// <param name="targetType">转换的目标类型</param>
/// <returns></returns>
object Convert(object value, Type targetType);
value和targetType千变万化,一口可吃不完,本着单一职责原则,我们应该要写很多转换单元,每个单元只负责一种类型转换,转换器由N多个转换单元组成,如果转换单元是中间件,抽象的中间件接口应该如下:
/// <summary>
/// 定义类型转换单元的接口
/// </summary>
public interface IConvertMiddleware
{
/// <summary>
/// 设置下一个转换单元
/// </summary>
IConvertMiddleware Next { set; } /// <summary>
/// 将value转换为目标类型
/// </summary>
/// <param name="上下文">context</param>
/// <returns></returns>
object Convert(ConvertContext context);
}
实际当中,我们可能未必需要这么抽象,我的实际接口是
/// <summary>
/// 定义类型转换单元的接口
/// </summary>
public interface IConvert
{
/// <summary>
/// 设置转换器
/// </summary>
Converter Converter { set; } /// <summary>
/// 设置下一个转换单元
/// </summary>
IConvert NextConvert { set; } /// <summary>
/// 将value转换为目标类型
/// </summary>
/// <param name="value">要转换的值</param>
/// <param name="targetType">转换的目标类型</param>
/// <returns></returns>
object Convert(object value, Type targetType);
}
然后,我们来一个一个地来实现转换单元:
某个单元的实现如下:
/// <summary>
/// 表示不作转换的转换单元
/// </summary>
public class NoConvert : IConvert
{
/// <summary>
/// 转换器实例
/// </summary>
public Converter Converter { get; set; } /// <summary>
/// 下一个转换单元
/// </summary>
public IConvert NextConvert { get; set; } /// <summary>
/// 将value转换为目标类型
/// </summary>
/// <param name="value">要转换的值</param>
/// <param name="targetType">转换的目标类型</param>
/// <returns></returns>
public object Convert(object value, Type targetType)
{
if (targetType == typeof(object))
{
return value;
} if (value != null && targetType == value.GetType())
{
return value;
} return this.NextConvert.Convert(value, targetType);
}
}
NoConvert
更广泛的Middleware
我近来在开发开源项目《NetworkSocket》,自从看到Microsoft.Owin之后的中间件之后,觉得Middleware可以在很多领域中使用,现在这个项目里的协议解析实现者都已经完全由中间件来开发,功能越来丰富,但复杂度感觉没有增大。看看下面代码,你应该能感觉到Middleware的甜味。
var listener = new TcpListener();
listener.Use<HttpMiddleware>();
listener.Use<JsonWebSocketMiddleware>();
listener.Use<FastMiddleware>();
listener.Start();
Middleware的艺术的更多相关文章
- redux深入理解之中间件(middleware)
理解reduce函数 reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值. arr.reduce([callback, initi ...
- 读书笔记:JavaScript DOM 编程艺术(第二版)
读完还是能学到很多的基础知识,这里记录下,方便回顾与及时查阅. 内容也有自己的一些补充. JavaScript DOM 编程艺术(第二版) 1.JavaScript简史 JavaScript由Nets ...
- 有趣的 CSS 像素艺术
原文地址:https://css-tricks.com/fun-times-css-pixel-art/#article-header-id-4 译者:nzbin 友情提示:由于国内网络的原因,Cod ...
- 你真的会玩SQL吗?透视转换的艺术
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 用Middleware给ASP.NET Core Web API添加自己的授权验证
Web API,是一个能让前后端分离.解放前后端生产力的好东西.不过大部分公司应该都没能做到完全的前后端分离.API的实现方式有很 多,可以用ASP.NET Core.也可以用ASP.NET Web ...
- [转]Writing Custom Middleware in ASP.NET Core 1.0
本文转自:https://www.exceptionnotfound.net/writing-custom-middleware-in-asp-net-core-1-0/ One of the new ...
- [转]用Middleware给ASP.NET Core Web API添加自己的授权验证
本文转自:http://www.cnblogs.com/catcher1994/p/6021046.html Web API,是一个能让前后端分离.解放前后端生产力的好东西.不过大部分公司应该都没能做 ...
- [译]Writing Custom Middleware in ASP.NET Core 1.0
原文: https://www.exceptionnotfound.net/writing-custom-middleware-in-asp-net-core-1-0/ Middleware是ASP. ...
- 解读ASP.NET 5 & MVC6系列(6):Middleware详解
在第1章项目结构分析中,我们提到Startup.cs作为整个程序的入口点,等同于传统的Global.asax文件,即:用于初始化系统级的信息(例如,MVC中的路由配置).本章我们就来一一分析,在这里如 ...
随机推荐
- 批处理脚本为Mysql重置root密码(重置密码为123456)
@echo off title mysql ::从注册表找到Mysql的安装路径写入文件mysql.txt reg query HKLM\SYSTEM\ControlSet001\Services\M ...
- Linux的文件时间
在windows下,一个文件有:创建时间.修改时间.访问时间.而在Linux下,一个文件也有三种时间,分别是:访问时间.修改时间.状态改动时间. 1.访问时间,读一次这个文件的内容,这个时间就会更新. ...
- [转]NopCommerce 多数据库方案
本文转自:http://www.cnblogs.com/YUTOUYUWEI/p/5538200.html 有时候一个项目需要连接多个数据库,以实现不同数据库的数据在同个项目的共享. 如果已经安装了n ...
- 睡觉问题早晚成为我顶头疼的问题。。。-PHP
hi 昨晚又作自己,睡不好整个人都不好... 1.PHP实现页面静态化 二.纯静态化 2.2 实现页面纯静态化的原理 --基本方式 file_put_contents()函数: 使用php内置缓存机制 ...
- hdu-5493 Queue(二分+树状数组)
题目链接: Queue Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- TopCoder SRM 639 Div.2 500 AliceGameEasy --乱搞
题意: 一个游戏有n轮,有A和B比赛,谁在第 i 轮得胜,就获得 i 分,给出x,y,问A得x分,B得y分有没有可能,如果有,输出A最少赢的盘数. 解法: 这题是我傻逼了,处理上各种不优越,要使n*( ...
- 分层开发之MySchool
No.1实现登陆功能,验证用户名和密码.从数据库里进行匹配,看是否有符合要求的数据. 在DAL层编写代码,返回值为布尔类型.方法参数为(student实体类对象),使用参数化SqlParameter类 ...
- 修复垂直滑动RecyclerView嵌套水平滑动RecyclerView水平滑动不灵敏问题
在 Android 应用中,大部分情况下都会使用一个垂直滚动的 View 来显示内容(比如 ListView.RecyclerView 等).但是有时候你还希望垂直滚动的View 里面的内容可以水平滚 ...
- git中的版本回退
git版本回退有两种情况,一种是从本地版本库中(head区)回退到某个版本,可以用命令 git reset --hard head^ 或git reset --hard head~x ,head指的是 ...
- HTML 学习笔记 CSS3 (多列)
CSS3多列 通过CSS3 我们能够创建多个列来对文本进行布局. 在这篇文章中 你将了解到如下多列属性: column-count column-gap column-rule 浏览器支持: 多列的属 ...