菜鳥入門【ASP.NET Core】8:Middleware管道介紹、自己動(dòng)手構(gòu)建Re...
中間件:是匯集到以處理請求和響應(yīng)的一個(gè)應(yīng)用程序管道的軟件。
每個(gè)組件:
可以選擇是否要將請求傳遞到管道中的下一個(gè)組件。
之前和之后調(diào)用管道中的下一個(gè)組件,可以執(zhí)行工作。
使用請求委托來生成請求管道。?請求委托處理每個(gè) HTTP 請求。
請求中使用委托來配置運(yùn)行,映射,和使用擴(kuò)展方法。?一個(gè)單獨(dú)的請求委托,它可將指定的在行作為匿名方法 (稱為中,線中間件),或可以在可重用的類中定義它。
?這些可重用的類和行在匿名方法中間件,或中間件組件。?在請求管道中的每個(gè)中間件組件負(fù)責(zé)調(diào)用管道中的下一個(gè)組件,或如果相應(yīng)短路鏈。
使用 IApplicationBuilder 創(chuàng)建中間件管道
ASP.NET 核心請求管道由請求委托,調(diào)用一次是在另一個(gè),如圖所示 (執(zhí)行如下所示的黑色箭頭的線程) 的順序組成:

?
我們可以鏈接多個(gè)請求委托連同app.use。?next參數(shù)表示管道中的下一步委托。我們一共有兩種辦法構(gòu)建管道:

然后執(zhí)行dotnet build生成項(xiàng)目后執(zhí)行 dotnet run 來運(yùn)行我們我們的程序
?
?如果我們在第二步的時(shí)候不調(diào)用Invoke會(huì)怎樣?我們先執(zhí)行 dotnet watch run
然后 我們再修改代碼:


IApplicationBuilder是用來構(gòu)建管道的,我們可以通過Use來注冊中間件,同時(shí)可以傳遞給我們一個(gè)next的Deletegate的委托。在這個(gè)情況下,我們可以調(diào)用下一步中間件的委托,如果我們不調(diào)用的話,后面的管道就終止了。
還有一點(diǎn)就是IApplicationBuilder會(huì)提供給我們一個(gè)Map,我們可以理解為路由的機(jī)制。

我們后面的路由也是在這個(gè)基礎(chǔ)上進(jìn)行配置的。運(yùn)行效果:

自己動(dòng)手構(gòu)建RequestDelegate管道
什么是RequestDelegate
ASP.NET Core的中間件通過一個(gè)類型Func<RequestDelegate, RequestDelegate>的委托對象來表示,而RequestDelegate也是一個(gè)委托,它代表一項(xiàng)請求處理任務(wù)。
每個(gè)中間件都承載著獨(dú)立的請求處理任務(wù),它本質(zhì)上也體現(xiàn)了在當(dāng)前HttpContext下針對請求的處理操作,那么為什么中間件不直接通過一個(gè)RequestDelegate對象來表示,而是表示為一個(gè)類型為Func<RequestDelegate, RequestDelegate>的委托對象呢?原因很簡單,中間件并不孤立地存在,所有注冊的中間件最終會(huì)根據(jù)注冊的先后順序組成一個(gè)鏈表,每個(gè)中間件不僅僅需要完成各自的請求處理任務(wù)外,還需要驅(qū)動(dòng)鏈表中的下一個(gè)中間件。
對于一個(gè)由多個(gè)Func<RequestDelegate, RequestDelegate>對象組成的中間鏈表來說,某個(gè)中間件會(huì)將后一個(gè)Func<RequestDelegate, RequestDelegate>對象的返回值作為輸入,而自身的返回值則作為前一個(gè)中間件的輸入。某個(gè)中間件執(zhí)行之后返回的RequestDelegate對象不僅僅體現(xiàn)了自身對請求的處理操作,而是體現(xiàn)了包含自己和后續(xù)中間件一次對請求的處理。那么對于第一個(gè)中間件來說,它執(zhí)行后返回的RequestDelegate對象實(shí)際上體現(xiàn)了整個(gè)應(yīng)用對請求的處理邏輯。
模擬RequestDelegate
首先先用VSCode新建一個(gè)控制臺(tái)項(xiàng)目:MyPipeline,然后打開
dotnet new console --name MyPipeline
新建一個(gè)Context.cs類


using System;
using System.Threading.Tasks;
namespace MyPipeline
{
public class Context
{
}
}


新建一個(gè)RequestDelegate.cs類


using System;
using System.Threading.Tasks;
namespace MyPipeline
{
public delegate Task RequestDelegate(Context context);
}


在Program.cs中聲明一個(gè)接收委托、返回委托的List,并初始化
public static List<Func<RequestDelegate,RequestDelegate>> _list=new List<Func<RequestDelegate,RequestDelegate>>();
模擬ApplicationBuilder中的app.Use方法
//模擬ApplicationBuilder中的app.Use方法
public static void Use(Func<RequestDelegate,RequestDelegate> middleware)
{
_list.Add(middleware);
}
在Main中調(diào)用


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);
}
//這時(shí)候我們沒有Context,所以直接new一個(gè)Context給它
end.Invoke(new Context());
Console.ReadLine();
}


結(jié)果:

這個(gè)時(shí)候我們在第一步進(jìn)行終止操作:

結(jié)果:

