但愿给你3-5分钟的碎片化学习,多是坐地铁、等公交,聚沙成塔,水滴石穿,谢谢关注。git
要了解管道的实现机制,咱们必需要深刻框架的源码,幸好微软开源了,咱们能够访问GitHub的地址来下载源码。github
git clone后,咱们打开工程,进入Microsoft.AspNetCore.Http项目搜索ApplicationBuilder类(以下图),RequestDelegate是中间件的核心,而ApplicationBuilder是接收多个RequestDelegate的集合,因此解析ApplicationBuilder是了解整个管道实现的重要内容。而ApplicationBuilder里有两个重要的方法Build和Use也是咱们关注的焦点。app
咱们看下Use方法的参数是一个委托,该委托接收一个RequestDelegate参数,返回一个RequestDelegate,而_components.Add(middleware);是什么呢?咱们看下这个全局变量的定义:框架
_components就是一个IList列表容器,也就是说Use方法作的事情很是简单,就是不断的把中间件middleware往容器里面加而已,而中间件是什么?就是一个由RequestDelegate构成的委托罢了。 学习
咱们知道Use还有一个重载方法,他是一个扩展方法,能够在UseExtensions找到(以下图),这个扩展方法其实也是调用上面的Use方法,往容器添加内容。测试
包括Run方法和上面相似,都是往容器灌入Middleware中间件。ui
Use完了以后,接下来作什么呢?咱们看下Build实现代码。spa
这里对RequestDelegate集合进行反转,而后逐一调用执行,因此app会被最后一个执行。最后只返回一个RequestDelegate code
接下来,咱们来模拟管道的构建过程,咱们先建两个类,一个是RequestDelegate.cs和HttpContext.cs。component
HttpContext.cs咱们假设没有任何实现:
RequestDelegate.cs定义一个委托
由于是模拟,因此咱们这里使用控制台来测试,dotnet new console --name iConsole
咱们在Program.cs实现核心代码以下:
using System; using System.Collections.Generic; using System.Threading.Tasks; namespace iConsole { class Program { private static readonly IList<Func<RequestDelegate, RequestDelegate>> _mycomponents = new List<Func<RequestDelegate, RequestDelegate>>(); static void Main(string[] args) { //如下是Lambada表达式的简写 Use(next => { return context => { Console.WriteLine("PipeLine 1……"); return next.Invoke(context); }; }); Use(next => { return context => { Console.WriteLine("PipeLine 2……"); return next.Invoke(context); }; }); RequestDelegate PipeLine_end = context => { Console.WriteLine("PipeLine_end……"); return Task.CompletedTask; }; foreach (var component in _mycomponents) { PipeLine_end = component(PipeLine_end); } PipeLine_end.Invoke(new HttpContext()); Console.ReadLine(); } public static void Use(Func<RequestDelegate,RequestDelegate> middleware) { _mycomponents.Add(middleware); } } }
dotnet run后效果以下,整个模拟过程结束,是否是很简单呢。
以上代码大部分是截图,截图看起来更加顺眼,虽然不方便复制,若是你想看完整代码能够访问个人GitHub地址
但愿以上分享对你有帮助,我是IT人张飞洪,入行10年有余,人不堪其忧,吾不改其乐,谢谢您关注