<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Dotnet Core異常處理的優(yōu)雅實踐

          共 3570字,需瀏覽 8分鐘

           ·

          2020-09-09 23:28

          異常處理,也可以做得很優(yōu)雅。

          ?

          一、前言

          異常處理的重要性,老司機都清楚。

          ?

          這篇文章,我們來理一下Dotnet Core異常處理的幾種方式。

          1. Try Catch方式

          2. Exception Filter方式

          3. 內(nèi)建的異常處理中間件

          4. 自定義的異常處理中間件

          這是目前使用比較多的幾種方式。其中,第1、2種其實算是一種,是C#兩個語言版本的東西。

          二、Try Catch方式

          這是最通常使用的一種方式。

          看例子:

          [HttpGet]
          public?IActionResult?Get()
          {
          ????try
          ????{
          ????????List<string>?example_list?=?null;
          ????????var?item_count??=?example_list.Count();
          ????????return?Ok(item_count);
          ????}
          ????catch?(Exception?ex)
          ????{
          ????????return?StatusCode(HttpContext.Response.StatusCode,?ex.Message);
          ????}
          }

          ?

          有時候,我們可能需要處理多種異常。

          catch?(Exception?ex)
          {
          ????if(ex.InnerException?==?null)
          ????????return?StatusCode(HttpContext.Response.StatusCode,?"error");
          ????else
          ????????return?StatusCode(HttpContext.Response.StatusCode,?"other?error");
          }

          在C# 6以后,Try Catch加了一個過濾Exception Filter語法,可以在catch后跟一個條件語句。上面這個catch可以寫為:

          catch?(Exception?ex)?when?(ex.InnerException?==?null)
          {
          ????return?StatusCode(HttpContext.Response.StatusCode,?"error");
          }
          catch?(Exception?ex)
          {
          ????return?StatusCode(HttpContext.Response.StatusCode,?"other?error");
          }

          在這個語法中,when后面是一個bool的判斷,為true則進入catch塊,為false則跳過。

          ?

          在C#中,異常是從內(nèi)向外逐層查找處理程序的,隨著查找層數(shù)的增加,性能會逐漸降低。

          概念上,try塊的運行效率和不加try塊的性能差不多,可以認為基本一致;但catch塊的性能會差很多。所以一般來說,一個基本的原則是,不要把trycatch作為程序的邏輯。

          但是,如果我們需要又需要記錄這個異常,該怎么辦?

          這時候,就可以利用Exception Filter語法。

          看代碼:

          [HttpGet]
          public?IActionResult?Get()
          {
          ????try
          ????{
          ????????List<string>?example_list?=?null;
          ????????var?item_count?=?example_list.Count();
          ????????return?Ok(item_count);
          ????}
          ????catch?(Exception?ex)?when?(log(ex))
          ????{
          ????}
          ????return?StatusCode(HttpContext.Response.StatusCode,?"error");
          }

          private?bool?log(Exception?ex)
          {
          ????Debug.Print(ex.Message);
          ????return?false;
          }

          在這個代碼中,when條件后跟了一個返回bool的方法。我們可以在這個方法中進行異常的記錄處理,然后返回false

          為什么要返回false呢?是因為我們要記錄異常,但為了性能的考慮,不希望代碼進入到catch塊。返回false后,程序執(zhí)行了log方法,卻又沒進入到catch塊。

          當然,如果你想進入到catch塊,那返回true就可以了。

          ?

          嗯。這一段能看明白就行了,這不算是一個常規(guī)的解決辦法,只能算一個旁門的小技巧。

          三、內(nèi)建的異常中間件

          內(nèi)建的異常處理,有兩個。

          一個是我們最常見的,在創(chuàng)建webapi類型的工程時,Startup.cs文件中已經(jīng)默認生成好的:

          public?void?Configure(IApplicationBuilder?app,?IWebHostEnvironment?env)
          {
          ????if?(env.IsDevelopment())
          ????{
          ????????app.UseDeveloperExceptionPage();
          ????}
          }

          這個app.UseDeveloperExceptionPage就是框架中用于顯示異常的詳細信息的中間件。

          ?

          另一個,是app.UseExceptionHandler,也是一個內(nèi)置的用來處理異常的中間件,可以這樣用:

          public?void?Configure(IApplicationBuilder?app,?IWebHostEnvironment?env)
          {
          ????app.UseExceptionHandler(para...);
          }

          參數(shù)可以是一個Endpoint,也可以是一個Action。實際應(yīng)用時,還可以寫成一個IApplicationBuilder的擴展。

          四、自定義的中間件

          如果對異常管理有很高的要求,自定義異常處理中間件,是最合適的一種方式。

          中間件的寫法,我在前文一文說通Dotnet Core的中間件中有詳細的說明,這兒不再多說。

          給一段例子看看:

          public?class?CustomExceptionMiddleware
          {

          ????private?readonly?RequestDelegate?_next;
          ????private?readonly?ILogger?_logger;
          ????public?CustomExceptionMiddleware(RequestDelegate?next,?ILogger?logger)
          ????
          {
          ????????_logger?=?logger;
          ????????_next?=?next;
          ????}
          ????public?async?Task?InvokeAsync(HttpContext?httpContext)
          ????
          {
          ????????try
          ????????{
          ????????????await?_next(httpContext);
          ????????}
          ????????catch?(Exception?ex)
          ????????{
          ????????????_logger.LogError($"Exception?occur:?{ex}");
          ????????????await?HandleExceptionAsync(httpContext,?ex);
          ????????}
          ????}
          ????private?Task?HandleExceptionAsync(HttpContext?context,?Exception?exception)
          ????
          {
          ????????context.Response.ContentType?=?"application/json";
          ????????context.Response.StatusCode?=?(int)HttpStatusCode.InternalServerError;
          ????????return?context.Response.WriteAsync(new?CustomError()
          ????????{
          ????????????StatusCode?=?context.Response.StatusCode,
          ????????????Message?=?"custom?middleware?error."
          ????????}.ToString());
          ????}
          }

          使用時,就在Configure里引入即可。

          ?

          (全文完)

          本文的代碼已上傳到Github,位置在:https://github.com/humornif/Demo-Code/tree/master/0023/demo/demo

          喜歡就來個三連,讓更多人因你而受益

          瀏覽 57
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产一级a毛一级a看免费视频黑人 | av大全在线观看 av电影在线一区 | 国产一二三四区 | 男人的天堂tv | 天天草天天草 |