1. 程式人生 > 實用技巧 >Dotnet Core異常處理的優雅實踐

Dotnet Core異常處理的優雅實踐

異常處理,也可以做得很優雅。

一、前言

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

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

  1. Try Catch方式
  2. Exception Filter方式
  3. 內建的異常處理中介軟體
  4. 自定義的異常處理中介軟體

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

為了防止不提供原網址的轉載,特在這裡加上原文連結:https://www.cnblogs.com/tiger-wang/p/13562817.html

二、Try Catch方式

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

看例子:

[HttpGet]
publicIActionResultGet()
{
try
{
List<string>example_list=null;
varitem_count=example_list.Count();
returnOk(item_count);
}
catch(Exceptionex)
{
returnStatusCode(HttpContext.Response.StatusCode,ex.Message);
}
}

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

catch(Exceptionex)
{
if(ex.InnerException==null)
returnStatusCode(HttpContext.Response.StatusCode,"error"
);
else
returnStatusCode(HttpContext.Response.StatusCode,"othererror");
}

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

catch(Exceptionex)when(ex.InnerException==null)
{
returnStatusCode(HttpContext.Response.StatusCode,"error");
}
catch(Exceptionex)
{
returnStatusCode(HttpContext.Response.StatusCode,"othererror"
);
}

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

在C#中,異常是從內向外逐層查詢處理程式的,隨著查詢層數的增加,效能會逐漸降低。

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

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

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

看程式碼:

[HttpGet]
publicIActionResultGet()
{
try
{
List<string>example_list=null;
varitem_count=example_list.Count();
returnOk(item_count);
}
catch(Exceptionex)when(log(ex))
{
}
returnStatusCode(HttpContext.Response.StatusCode,"error");
}

privateboollog(Exceptionex)
{
Debug.Print(ex.Message);
returnfalse;
}

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

為什麼要返回false呢?是因為我們要記錄異常,但為了效能的考慮,不希望程式碼進入到catch塊。返回false後,程式執行了log方法,卻又沒進入到catch塊。

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

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

三、內建的異常中介軟體

內建的異常處理,有兩個。

一個是我們最常見的,在建立webapi型別的工程時,Startup.cs檔案中已經預設生成好的:

publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
}

這個app.UseDeveloperExceptionPage就是框架中用於顯示異常的詳細資訊的中介軟體。

另一個,是app.UseExceptionHandler,也是一個內建的用來處理異常的中介軟體,可以這樣用:

publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv)
{
app.UseExceptionHandler(para...);
}

引數可以是一個Endpoint,也可以是一個Action。實際應用時,還可以寫成一個IApplicationBuilder的擴充套件。

四、自定義的中介軟體

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

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

給一段例子看看:

publicclassCustomExceptionMiddleware
{

privatereadonlyRequestDelegate_next;
privatereadonlyILogger<CustomExceptionMiddleware>_logger;
publicCustomExceptionMiddleware(RequestDelegatenext,ILogger<CustomExceptionMiddleware>logger)
{
_logger=logger;
_next=next;
}
publicasyncTaskInvokeAsync(HttpContexthttpContext)
{
try
{
await_next(httpContext);
}
catch(Exceptionex)
{
_logger.LogError($"Exceptionoccur:{ex}");
awaitHandleExceptionAsync(httpContext,ex);
}
}
privateTaskHandleExceptionAsync(HttpContextcontext,Exceptionexception)
{
context.Response.ContentType="application/json";
context.Response.StatusCode=(int)HttpStatusCode.InternalServerError;
returncontext.Response.WriteAsync(newCustomError()
{
StatusCode=context.Response.StatusCode,
Message="custommiddlewareerror."
}.ToString());
}
}

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

(全文完)

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


微信公眾號:老王Plus

掃描二維碼,關注個人公眾號,可以第一時間得到最新的個人文章和內容推送

本文版權歸作者所有,轉載請保留此宣告和原文連結