4.5管道實現機制和模擬構建管道「深入淺出ASP.NET Core系列」

希望給你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年有餘,人不堪其憂,吾不改其樂,謝謝您關注我的頭條號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章