一、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