ASP.NET Core 3.1--中間件源碼解讀--RequestDelegate--ApplicationBuilder.Use

一、RequestDelegate的定義
從RequestDelegate定義可以看出,RequestDelegate是接收請求上下文HttpContext的一個委託,RequestDelegate既然是一個委託,委託就是一個方法,所以RequestDelegate就是個方法,是個接受請求上下文的方法。

public delegate Task RequestDelegate(HttpContext context);

二、 IApplicationBuilder.Use的定義
我們對比來看,下面這個func是接收1個int 類型的參數,返回1個string類型的委託

Func<int, string> func = new Func<int, string>(i => 
{
    return "abc";
});
string result = func(123);

在看ApplicationBuilder.Use()的定義
ApplicationBuilder.Use方法接收1個Func委託,這個Func接收1個RequestDelegate類型的參數,返回1個RequestDelegate類型,上面說了RequestDelegate是個方法,那麼也就是說ApplicationBuilder.Use方法接收1個方法,返回1個方法。

IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);

三、ApplicationBuilder.Use需要的參數的簡寫
這時候requestdelegate是個方法,但是是什麼方法,我們還不知道,我們往下看

//1、Func委託,這個Func接收1個RequestDelegate類型的參數,返回1個RequestDelegate類型
Func<RequestDelegate, RequestDelegate> func = new Func<RequestDelegate, RequestDelegate>((RequestDelegate requestdelegate) =>
{
    return new RequestDelegate(async (context) =>
    {
        await context.Response.WriteAsync("接收1個帶RequestDelegate類型的參數,返回RequestDelegate類型的委託");
    });
});

//2、簡寫這個委託
Func<RequestDelegate, RequestDelegate> func = (requestdelegate =>
{
    return new RequestDelegate(async (context) =>
    {
        await context.Response.WriteAsync("簡寫func委託!");
    });
});

//3、Use中間件,最終簡寫
app.Use(requestdelegate =>
{
    return new RequestDelegate(async (context) =>
    {
        await context.Response.WriteAsync("Use中間件!");
    });
});

四、看源碼解讀中間件註冊和執行流程
爲什麼輸出順序是This is Middleware 3--->This is Middleware 2--->This is Middleware 1
爲什麼輸出順序是This is Hello World 1 Start--->This is Hello World 2 Start--->This is Hello World 3 Start--->This is Hello World 3 End--->This is Hello World 2 End--->This is Hello World 1 End

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{ 
    app.Use(next =>
    {
        Console.WriteLine("This is Middleware 1");
        return new RequestDelegate(
            async context =>
            {
                await context.Response.WriteAsync("This is Hello World 1 Start");
                await next.Invoke(context);
                await context.Response.WriteAsync("This is Hello World 1 End");
            });
    });
    app.Use(next =>
    {
        Console.WriteLine("This is Middleware 2");
        return new RequestDelegate(
            async context =>
            {
                await context.Response.WriteAsync("This is Hello World 2 Start");
                await next.Invoke(context);
                await context.Response.WriteAsync("This is Hello World 2 End");
            });
    });
    app.Use(next =>
    {
        Console.WriteLine("This is Middleware 3");
        return new RequestDelegate(
            async context =>
            {
                await context.Response.WriteAsync("This is Hello World 3 Start");
                await context.Response.WriteAsync("This is Hello World 3 End");
            });
    });  
}

1、ApplicationBuilder.Use方法源碼解讀
從源碼看出ApplicationBuilder.Use方法就是把Func<RequestDelegate, RequestDelegate> middleware添加到_components這個集合裏,而從_components的定義看出_components是個委託集合。

 

2、中間件執行源碼解讀
從源碼看出有個默認的RequestDelegate app,把委託集合反轉,遍歷執行。
所以先輸出This is Middleware 3,後輸出This is Middleware 2,最後輸出This is Middleware 1,最終返回的是第1箇中間件。

第3箇中間件的傳入參數是默認的RequestDelegate app
第2箇中間件的傳入參數是第3箇中間件的返回值
第1箇中間件的傳入參數是第2箇中間件的返回值

第3箇中間件的next是默認的RequestDelegate app
第2箇中間件的next是第3箇中間件的返回值
第1箇中間件的next是第2箇中間件的返回值
所以最後的輸出順序是This is Hello World 1 Start--->This is Hello World 2 Start--->This is Hello World 3 Start--->This is Hello World 3 End--->This is Hello World 2 End--->This is Hello World 1 End

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