希望給你3-5分鐘的碎片化學習,可能是坐地鐵、等公交,積少成多,水滴石穿,謝謝關注。
管道實現機制
要了解管道的實現機制,我們必須要深入框架的源碼,幸虧微軟開源了,我們可以訪問GitHub的地址來下載源碼。
git clone後,我們打開工程,進入Microsoft.AspNetCore.Http項目搜索ApplicationBuilder類(如下圖),RequestDelegate是中間件的核心,而ApplicationBuilder是接收多個RequestDelegate的集合,所以解析ApplicationBuilder是瞭解整個管道實現的重要內容。而ApplicationBuilder裏有兩個重要的方法Build和Use也是我們關注的焦點。
Use方法
我們看下Use方法的參數是一個委託,該委託接收一個RequestDelegate參數,返回一個RequestDelegate,而_components.Add(middleware);是什麼呢?我們看下這個全局變量的定義:
_components就是一個IList列表容器,也就是說Use方法做的事情非常簡單,就是不斷的把中間件middleware往容器裏面加而已,而中間件是什麼?就是一個由RequestDelegate構成的委託罷了。
我們知道Use還有一個重載方法,他是一個擴展方法,可以在UseExtensions找到(如下圖),這個擴展方法其實也是調用上面的Use方法,往容器添加內容。
包括Run方法和上面類似,都是往容器灌入Middleware中間件。
Build方法
Use完了之後,接下來做什麼呢?我們看下Build實現代碼。
這裏對RequestDelegate集合進行反轉,然後逐一調用執行,所以app會被最後一個執行。最後只返回一個RequestDelegate
模擬構建管道
接下來,我們來模擬管道的構建過程,我們先建兩個類,一個是RequestDelegate.cs和HttpContext.cs。
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地址
希望以上分享對你有幫助,我是張飛洪,入行10年有餘,人不堪其憂,吾不改其樂,謝謝您關注我的頭條號