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中的路由配置).本章我们就来一一分析,在这里如 ...
随机推荐
- crontab执行不生效-【问题篇】
背景:shell脚本每隔两分钟从数据库取数据库放到脚本所在目录,做好计划任务发现不生效. 解决:脚本中文件路径问题 测试:在/data/test目录下写的脚本,直接在本目录touch以分钟结尾的文件. ...
- SQLHelp帮助类
public readonly static string connStr = ConfigurationManager.ConnectionStrings["conn"].Con ...
- python基础(六)循环
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 循环用于重复执行一些程序块.从上一讲的选择结构,我们已经看到了如何用缩进来表示程序 ...
- Python基础-day2
1.Python模块python 中导入模块使用import语法格式:import module_name示例1: 导入os模块system('dir')列出当前目录下的所有文件 # _*_ codi ...
- ES6块级作用域及新变量声明(let)
很多语言中都有块级作用域,但JS没有,它使用var声明变量,以function来划分作用域,大括号“{}” 却限定不了var的作用域.用var声明的变量具有变量提升(declaration hoist ...
- 虚拟机centos6.5 --ssh免密码登录
说明:此处是以hadoop虚拟机3台机器为背景进行设置,即master.slave01.slave02 1.在master上,生成公钥.私钥 用hadoop用户登录系统,进入个人主目录,即/home/ ...
- 中国版的 Office 365
与Windows Azure一样,中国版的Office 365也是由世纪互联运营的——与国际版完全隔离的定制版.而言,从功能方面来看,中国版的Office 365并没有损失太多功能,并且其更新速度也基 ...
- Core Dump [Linux]
I have known Core-Dump for a long time. But I just know it little. Now, I am about to study it.
- Unity3D中的预制件(Prefab)的创建和使用说明!!!
首先我说明一下什么预制件? 在U3D里面我们叫它Prefab:我们可以这样理解:当制作好了游戏组件(场景中的任意一个gameobject),我们希望将它制作成一个组件模版,用于批量的套用工作,例如说场 ...
- 在Flex4中嵌入字体
如果要使用的字体不是系统字体,可以把字体嵌入到Flash中,然后引用该字体.不过字体文件一般都比较大,慎重使用该功能. 官方例子 http://help.adobe.com/en_US/flex/us ...