中間件是聚集到以處理請求和響應的一個應用程序管道的軟件。 每一個組件:api
使用請求委託來生成請求管道。 請求委託處理每一個 HTTP 請求。app
請求中使用委託來配置運行,映射,和使用擴展方法。 一個單獨的請求委託,它可將指定的在行做爲匿名方法 (稱爲中,線中間件),或能夠在可重用的類中定義它。 這些可重用的類和行在匿名方法中間件,或中間件組件。 在請求管道中的每一箇中間件組件負責調用管道中的下一個組件,或若是相應短路鏈。ui
ASP.NET 核心請求管道由請求委託,調用一次是在另外一個,如圖所示 (執行以下所示的黑色箭頭的線程) 的順序組成:spa
咱們能夠連接多個請求委託連同app.use。 next
參數表示管道中的下一步委託。咱們一共有兩種辦法構建管道:線程
而後執行dotnet build生成項目後執行 dotnet run 來運行咱們咱們的程序3d
若是咱們在第二步的時候不調用Invoke會怎樣?咱們先執行 dotnet watch runcode
而後 咱們再修改代碼:中間件
IApplicationBuilder是用來構建管道的,咱們能夠經過Use來註冊中間件,同時能夠傳遞給咱們一個next的Deletegate的委託。在這個狀況下,咱們能夠調用下一步中間件的委託,若是咱們不調用的話,後面的管道就終止了。對象
還有一點就是IApplicationBuilder會提供給咱們一個Map,咱們能夠理解爲路由的機制。blog
咱們後面的路由也是在這個基礎上進行配置的。運行效果:
ASP.NET Core的中間件經過一個類型Func<RequestDelegate, RequestDelegate>的委託對象來表示,而RequestDelegate也是一個委託,它表明一項請求處理任務。
每一箇中間件都承載着獨立的請求處理任務,它本質上也體現了在當前HttpContext下針對請求的處理操做,那麼爲何中間件不直接經過一個RequestDelegate對象來表示,而是表示爲一個類型爲Func<RequestDelegate, RequestDelegate>的委託對象呢?緣由很簡單,中間件並不孤立地存在,全部註冊的中間件最終會根據註冊的前後順序組成一個鏈表,每一箇中間件不單單須要完成各自的請求處理任務外,還須要驅動鏈表中的下一個中間件。
對於一個由多個Func<RequestDelegate, RequestDelegate>對象組成的中間鏈表來講,某個中間件會將後一個Func<RequestDelegate, RequestDelegate>對象的返回值做爲輸入,而自身的返回值則做爲前一箇中間件的輸入。某個中間件執行以後返回的RequestDelegate對象不單單體現了自身對請求的處理操做,而是體現了包含本身和後續中間件一次對請求的處理。那麼對於第一個中間件來講,它執行後返回的RequestDelegate對象實際上體現了整個應用對請求的處理邏輯。
首先先用VSCode新建一個控制檯項目:MyPipeline,而後打開
dotnet new console --name MyPipeline
新建一個Context.cs類
using System; using System.Threading.Tasks; namespace MyPipeline { public class Context { } }
新建一個RequestDelegate.cs類
using System; using System.Threading.Tasks; namespace MyPipeline { public delegate Task RequestDelegate(Context context); }
在Program.cs中聲明一個接收委託、返回委託的List,並初始化
public static List<Func<RequestDelegate,RequestDelegate>> _list=new List<Func<RequestDelegate,RequestDelegate>>();
//模擬ApplicationBuilder中的app.Use方法 public static void Use(Func<RequestDelegate,RequestDelegate> middleware) { _list.Add(middleware); }
在Main中調用
static void Main(string[] args) { //第一步 Use(next=>{ return context=>{ System.Console.WriteLine("1"); return next.Invoke(context); //return Task.CompletedTask; }; }); //第二步 Use(next=>{ return context=>{ System.Console.WriteLine("2"); return next.Invoke(context); }; }); RequestDelegate end=(context)=>{ System.Console.WriteLine("end..."); return Task.CompletedTask; }; _list.Reverse(); foreach(var middleware in _list) { end=middleware.Invoke(end); } //這時候咱們沒有Context,因此直接new一個Context給它 end.Invoke(new Context()); Console.ReadLine(); }
結果:
這個時候咱們在第一步進行終止操做:
結果: