亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

ASP.NET?Core自定義中間件的方式詳解

 更新時間:2022年08月20日 10:01:18   作者:姜承軒  
這篇文章主要介紹了ASP.NET?Core自定義中間件的方式,雖然ASP.NET?Core為我們提供了一組豐富的內(nèi)置中間件,但有些時候我們可能會需要自定義一些中間件,將其穿插到管道中,以便滿足我們特定業(yè)務(wù)場景的需求,所以本文將介紹3種方式來滿足自定義中間件的需求

ASP.NET Core應(yīng)用本質(zhì)上,其實就是由若干個中間件構(gòu)建成的請求處理管道。管道相當(dāng)于一個故事的框架,而中間件就相當(dāng)于故事中的某些情節(jié)。同一個故事框架采用不同的情節(jié)拼湊,最終會體現(xiàn)出不同風(fēng)格的故事。而我們的ASP.NET Core應(yīng)用也正是如此,同一管道采用不同的中間件組合,最終也會呈現(xiàn)出不同的應(yīng)用形態(tài)。

從上述的概念種可以看出,中間件在ASP.NET Core應(yīng)用有著舉足輕重的地位。雖然ASP.NET Core為我們提供了一組豐富的內(nèi)置中間件,但有些時候我們可能會需要自定義一些中間件,將其穿插到管道中,以便滿足我們特定業(yè)務(wù)場景的需求,所以本文將介紹3種方式來滿足自定義中間件的需求。

1.委托形式

在應(yīng)用程序代碼中,我們可以從用于注冊中間件的Use方法中看出,所謂管道中的中間件其實就是一種委托類型的對象,這個具體的委托對象體現(xiàn)為“Fun<RequestDelegate,RequestDelegate>”。

從Fun<RequestDelegate,RequestDelegate>委托的定義可以看出,該委托類型的入?yún)⒑头祷刂刀际且粋€RequestDelegate委托類型的對象。RequestDelegate委托類型其實就是管道在代碼中的體現(xiàn)形式,該委托類型承載很多關(guān)于請求響應(yīng)的重要信息,定義如下:

public delegate Task RequestDelegate(HttpContext context);

Fun<RequestDelegate,RequestDelegate>委托中,入?yún)⒌腞equestDelegate對象表示由上一個中間件構(gòu)建的管道,返回值的RequestDelegate對象表示:將當(dāng)前中間件基于上一個管道處理后生成的新管道。由于中間件體現(xiàn)為一個Fun<RequestDelegate,RequestDelegate>委托對象,那么這就代表我們可以定義一個與該委托具有一致聲明的方法作為自定義中間件的方式。具體的代碼實現(xiàn)方式如下:

//創(chuàng)建應(yīng)用
var app = WebApplication.Create(args);

//轉(zhuǎn)換獲得應(yīng)用建造者
IApplicationBuilder appBuilder = app;

//注冊自定義的中間件
appBuilder.Use(SayHi);

//運(yùn)行應(yīng)用
app.Run();

//定義為Fun<RequestDelegate,RequestDelegate>類型的方法
static RequestDelegate SayHi(RequestDelegate  request)
    => httpContext => httpContext.Response.WriteAsync("Hello");

上面的代碼是在一個原始的控制臺程序中編寫的,并且自行進(jìn)行了主機(jī)應(yīng)用的構(gòu)建。在代碼中定義了一個和Fun<RequestDelegate,RequestDelegate>委托簽名一致的SayHi方法,并以此方法作為中間件進(jìn)行了引用。雖然這是一個可行的方式,但在實際開發(fā)的工作場景中,其實很少會使用委托形式作為自定義中間件的方式。在此處之所以演示這種形式,主要是為了表面中間件本質(zhì)是一個委托,并且不管通過什么形式去定義中間件,它最終都會體現(xiàn)為一個Fun<RequestDelegate,RequestDelegate>委托對象。

2.強(qiáng)類型中間件

在實際的開發(fā)過程中,基本上都會將自定義的中間件定義為一個具體類型,而對于使用強(qiáng)類型的中間件而言,則我們定義的中間件類型必須實現(xiàn)IMiddleware接口。既然通過一個具體類型來定義中間件,類型在使用上則勢必會與其他類型產(chǎn)生依賴關(guān)聯(lián)性,那么對于中間件類型中依賴服務(wù)的實例化,框架則要求我們使用依賴注入的方式。接下來我們將通過代碼示例演示如何定義一個強(qiáng)類型的中間件。

2.1.定義中間件的依賴

下面代碼定義的類型是我們預(yù)先為中間件類型定義的依賴項,ISeasonTips接口類型的作用主要是,根據(jù)不同月份獲取對應(yīng)的季節(jié),并輸出對應(yīng)季節(jié)的注意事項,其中SeasonTips類型是接口的默認(rèn)實現(xiàn)。

public interface ISeasonTips
    {
        string Prompt(DateTimeOffset time);
    }

    public class SeasonTips : ISeasonTips
    {
        //根據(jù)不同月份提示季節(jié)注意事項
        public string Prompt(DateTimeOffset time) => time.Month switch
        {
            var h when h >= 3 && h <= 5 => "春天到了,早晚溫差比較大,要注意別感冒。",
            var h when h >= 6 && h <= 8 => "夏天到了,天氣炎熱,要注意別防嗮。",
            var h when h >= 9 && h <= 11 => "秋天到了,天氣干燥,要注意多喝水。",
            _ => "冬天到了,天氣寒冷,要注意防寒保暖。"

        }; //END Prompt()  

    }

2.2.定義中間件類型

下面的代碼中,我們定義了一個名為SeasonMiddleware的中間件類型,并實現(xiàn)IMiddleware接口。該中間件的處理請求的邏輯在InvokeAsync方法中,該方法調(diào)用其依賴類型的Prompt方法,根據(jù)當(dāng)前時間獲取當(dāng)前季節(jié)的注意事項進(jìn)行輸出。在該調(diào)用該方法后,我們還對InvokeAsync的另一個參數(shù):“RequestDelegate類型的委托對象”進(jìn)行了調(diào)用,以便執(zhí)行管道中的下一個中間件。另外,對于中間件依賴的類型ISeasonTips,我們將其定義在構(gòu)造函數(shù)的參數(shù)列表上,以便依賴注入容器提供相應(yīng)的實例。

/// <summary>
    /// 強(qiáng)類型中間件
    /// </summary>
    public class SeasonMiddleware : IMiddleware
    {
        //依賴類型,通過構(gòu)造函數(shù)進(jìn)行依賴注入
        private readonly ISeasonTips _seasonTips;
        public SeasonMiddleware(ISeasonTips seasonTips)
        {
            _seasonTips = seasonTips;
        }

        //調(diào)用依賴的“季節(jié)提示類型”,根據(jù)當(dāng)前時間獲取當(dāng)前季節(jié)的注意事項,并進(jìn)行響應(yīng)輸出
        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            await context.Response.WriteAsync(_seasonTips.Prompt(DateTimeOffset.Now));

            //調(diào)用管道中的下一個中間件
            await next(context);
        }  // END InvokeAsync()

    }  // END Class

在下面的代碼中我們對自定義的“強(qiáng)類型中間件”進(jìn)行了應(yīng)用。由于“強(qiáng)類型中間件”的實例以及依賴都是由依賴注入容器提供的,所以不僅要對依賴的服務(wù)進(jìn)行注冊,還要對自身的中間件類型進(jìn)行服務(wù)注冊。在服務(wù)注冊之后,我們使用WebApplication對象的UseMiddleware<SeasonMiddleware>擴(kuò)展方法,將該中間件添加到應(yīng)用程序的請求管道中。由于在該中間件后沒有其他中間件的處理,所以我們通過調(diào)用Run擴(kuò)展方法注冊了管道末端的中間件,以便結(jié)束當(dāng)前請求,將響應(yīng)輸出到客戶端。

using dotNet6Demo;

//創(chuàng)建“應(yīng)用建造者”
var builder = WebApplication.CreateBuilder(args);

//服務(wù)注冊
builder.Services.AddSingleton<ISeasonTips, SeasonTips>().AddSingleton<SeasonMiddleware>();

//構(gòu)建應(yīng)用
var app = builder.Build();

//引用強(qiáng)類型中間件
app.UseMiddleware<SeasonMiddleware>();

//末端的中間件
app.Run(async (context) =>
{
    await context.Response.WriteAsync("請求結(jié)束");
});

//運(yùn)行應(yīng)用
app.Run();

到目前為止,結(jié)合本示例以上的3個步驟,啟動運(yùn)行程序就可以驗證自定義強(qiáng)類型中間件的效果了。

3.基于約定的中間件

對于ASP.NET的開發(fā)者而言,基于約定的編程模式應(yīng)該不會陌生。例如在ASP.NET MVC框架中,“Action”默認(rèn)查找視圖就有一種基于約定的規(guī)則,即“Action”首先會在Views目錄中查找與當(dāng)前“Controller”同名的目錄,然后在該目錄中查找與“Action”同名的視圖文件。這種基于約定的設(shè)計方式,在自定義中間件領(lǐng)域也同樣使用到了,即基于約定的中間件。

3.1.約定規(guī)則

基于約定的中間件它不必像強(qiáng)類型中間件那樣,必須實現(xiàn)IMiddleware接口或繼承某些基類,它只用按照框架約定的方式定義中間件類型即可,具體的約定規(guī)則如下:

  1. 中間件類型必須要定義為一個公共的、可供外界實例化的類型,靜態(tài)類型無效;
  2. 構(gòu)造函數(shù)的參數(shù)中必須包含RequestDelegate類型,如果存在依賴類型則也必須包含在構(gòu)造函數(shù)中;

必須定義InvokeAsync或Invoke方法,方法簽名為:public Task Invoke(HttpContext context);

對以上的約定進(jìn)行一個補(bǔ)充說明:構(gòu)造函數(shù)的參數(shù)列表要包含依賴的類型,是為了依賴注入容器對依賴類型提供實例;RequestDelegate參數(shù)具有傳遞性,表示由后續(xù)中間件構(gòu)建的管道,當(dāng)前中間件利用它將請求轉(zhuǎn)交給后續(xù)管道進(jìn)行處理。InvokeAsync或Invoke方法主要是代表中間件在管道中處理請求的邏輯。

3.2.應(yīng)用實現(xiàn)

下面我們在“強(qiáng)類型中間件”示例的基礎(chǔ)上,根據(jù)約定規(guī)則將SeasonMiddleware類型改造為“基于約定的中間件”,代碼如下:

/// <summary>
    /// 基于約定的中間件
    /// </summary>
    public class SeasonMiddleware
    {
        private readonly ISeasonTips _seasonTips;
        private readonly RequestDelegate _next;

        public SeasonMiddleware(ISeasonTips seasonTips, RequestDelegate next)
        {
            _seasonTips = seasonTips;
            _next = next;
        }

        //調(diào)用依賴的“季節(jié)提示類型”,根據(jù)當(dāng)前時間獲取當(dāng)前季節(jié)的注意事項,并進(jìn)行響應(yīng)輸出
        public async Task InvokeAsync(HttpContext context)
        {
            await context.Response.WriteAsync(_seasonTips.Prompt(DateTimeOffset.Now));
            //調(diào)用管道中的下一個中間件
            await _next(context);

        }  // END InvokeAsync()

    }  // END Class

在中間件引用方面,“基于約定的中間件”同樣可以使用“app.UseMiddleware<SeasonMiddleware>()”的方式進(jìn)行引用,但是在此我們介紹一種較為常用的方式,就是將自定義中間件的引用方式進(jìn)行封裝,將其作為IApplicationBuilder類型的擴(kuò)展方法來使用,擴(kuò)展方法定義的代碼如下:

public static class SeasonMiddlewareExtensions
    {
        public static IApplicationBuilder UseSeason(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<SeasonMiddleware>();
        }
    }

接下來在示例應(yīng)用方面,將其調(diào)整為使用“基于約定中間件”的形式,并使用擴(kuò)展方法引用中間件。

using dotNet6Demo;

//創(chuàng)建“應(yīng)用建造者”
var builder = WebApplication.CreateBuilder(args);

//服務(wù)注冊
builder.Services.AddSingleton<ISeasonTips, SeasonTips>();

//構(gòu)建應(yīng)用
var app = builder.Build();

//通過自定義擴(kuò)展方法 引用中間件
app.UseSeason();

//末端的中間件
app.Run(async (context) =>
{
    await context.Response.WriteAsync("請求結(jié)束");
});

//運(yùn)行應(yīng)用
app.Run();

在對以上中間件應(yīng)用方面,我們能可以看出“基于約定的中間件”類型并沒有進(jìn)行服務(wù)注冊,而“強(qiáng)類型中間件”類型卻進(jìn)行了服務(wù)注冊,這是因為兩者在提供實例的方式上有著本質(zhì)的區(qū)別。

“基于約定的中間件”的實例是在應(yīng)用啟動時便可提供的,并且只能指定的一個固定的生命周期模式“Singleton”,所以該類型中間件具有和應(yīng)用程序一樣的生存期,直到應(yīng)用程序關(guān)閉才會釋放。

“強(qiáng)類型中間件”的實例并不是在應(yīng)用啟動時提供的,它需要根據(jù)服務(wù)注冊時指定的生命周期,來決定創(chuàng)建提供的時機(jī)。例如“強(qiáng)類型中間件”注冊的生命周期為“Scoped”,那么依賴注入容器會根據(jù)客戶端的請求實時創(chuàng)建中間件的實例,請求處理完成后才會被釋放。

總結(jié)

中間件的使用地位在ASP.NET Core中絕對是毋庸置疑的,那么對于較為復(fù)雜的項目而言,自定義中間件的需求絕對是“繞不開的彎”,所以我們必須掌握自定義中間件的方式。

本文介紹了3種可以實現(xiàn)自定義ASP.NET Core中間件的方式。其中第一種并不推崇作為實戰(zhàn)運(yùn)用的手段,其目的是為了讓我們明白:中間件最終的體現(xiàn)形式其實就是一個委托對象,該委托對象承載了請求上下信息,并具有傳遞性。在實際的使用中,我們可以在第二種和第三種中進(jìn)行選擇,也就是“強(qiáng)類型中間件”和“基于約定的中間件”,從兩者的特點上來看,“基于約定的中間件”在使用方面會更加的方便,但是其生命周期模式只能局限于Singleton。而“強(qiáng)類型中間件”可以通過服務(wù)注冊為中間件實例指定任意的生命周期模式,相比更加靈活。

對于具體的選擇,我們想我們還是交給我們實際的運(yùn)用場景。

如果想了解更多關(guān)于自定義 ASP.NET Core 中間件的方式,可以訪問如下的官方文檔:

寫入自定義 ASP.NET Core 中間件 | Microsoft Docs

到此這篇關(guān)于ASP.NET Core自定義中間件的方式的文章就介紹到這了,更多相關(guān)ASP.NET Core自定義中間件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論