1. 程式人生 > >4.4管道Middleware簡介「深入淺出ASP.NET Core系列」

4.4管道Middleware簡介「深入淺出ASP.NET Core系列」

希望給你3-5分鐘的碎片化學習,可能是坐地鐵、等公交,積少成多,水滴石穿,謝謝關注。

管道流

  瞭解管道流機制,就能知道如何利用管道進行攔截,自定義封裝等高階操作,所以學習管道流機制對我們編碼有質的提高。那麼管道資料是如何流通的呢?如下圖所示,Request進入管道Middleware 1,疊加一層邏輯程式碼到HttpContext(切確說是HttpContext的Response物件),然後呼叫next()進入到下一個管道Middleware 2,依次遞推,最後所有的邏輯程式碼疊加完畢後返回前端。

管道實踐

  實現自定義管道有兩種方法,使用IApplicationBuilder的Use和Run方法,他們的區別在下面會談到。

app.Use方法

  這裡先了解Use方法的第一個過載,如下圖所示,他是一個型別為委託的中介軟體(middleware)。

  這個中介軟體同時攜帶一個next的RequestDelegate委託,可以實現呼叫下一個管道中介軟體,我們看下程式碼實踐,如下所示,context從當前管道進來,處理後,通過next.Invoke()轉移到下一個管道,完成一個管道的生命週期。

   其實我更喜歡截圖,因為可以任意打標註,但是不方便拷貝,所以一起貼上程式碼吧。

app.Use(async (context, next) =>
{
     await context.Response.WriteAsync("fisrt……");
     await next.Invoke();
});

  以上的用法,如果是新手可能不知其所以然,用沒問題,但是內部是如何實現的?不知道!其實這裡使用到了語言的高階特性委託,通過委託實現了開閉原則,也就是把管道的擴充套件開放出來,我們可以使用規定的app.Use方法,但是內部定義的委託引數型別,比如context,Fun<task>則對外遮蔽了實現。所以你看到的next.Invoke()已經封裝了具體的實現了,對於使用者,其實可以不用去管那麼多,拿來用即可。

  app.Use還有另外一個過載,如下圖提示:這裡Func傳入一個RequestDelegate,返回一個RequestDelegate。不同於第一個過載,他沒有next.Invoke()的呼叫,而是之間返回一個RequestDelegate給app進行處理。

    我們看下程式碼實現,外層紅色框是傳入的管道,內部綠色框是返回的管道。

 app.Run

app.Run和app.Use不同之處在於,app.Use可以呼叫下一個中介軟體的管道,app.Run不會,我們演示一段程式碼。

    app.Use(async (context, next) =>
    {
        await context.Response.WriteAsync("<html><body>");
        await context.Response.WriteAsync("<div>Inside middleware defined using app.Use</div>");
        await next();
        await context.Response.WriteAsync("</body></html>");
    });
 
    app.Run(async context => { 
       await context.Response.WriteAsync("<div>Inside middleware defined using app.Run</div>"); 
    });
 
   //該管道會不會被列印呢? app.Use(
async (context, next) => { await context.Response.WriteAsync("<html><body>"); await context.Response.WriteAsync("<div>Another Middleware defined using app.Use</div>"); await next(); await context.Response.WriteAsync("</body></html>"); });

如下圖所示,我們看到Run後面定義的第二個Use沒有打印出來,這是因為Run不會呼叫隨後的管道導致的,所以我們一般習管性把Run方法放在所有管道的最後。 

 希望以上分享對你有幫助,我是張飛洪,入行10年有餘,人不堪其憂,吾不改其樂,謝謝您關注我的頭條