欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

Dotnet Core异常处理的优雅实践

发布时间:2023/12/4 57 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Dotnet Core异常处理的优雅实践 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

异常处理,也可以做得很优雅。

一、前言

异常处理的重要性,老司机都清楚。

这篇文章,我们来理一下Dotnet Core异常处理的几种方式。

  • Try Catch方式

  • Exception Filter方式

  • 内建的异常处理中间件

  • 自定义的异常处理中间件

  • 这是目前使用比较多的几种方式。其中,第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");elsereturn 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#中,异常是从内向外逐层查找处理程序的,随着查找层数的增加,性能会逐渐降低。

    概念上,try块的运行效率和不加try块的性能差不多,可以认为基本一致;但catch块的性能会差很多。所以一般来说,一个基本的原则是,不要把try、catch作为程序的逻辑。

    但是,如果我们需要又需要记录这个异常,该怎么办?

    这时候,就可以利用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后,程序执行了log方法,却又没进入到catch块。

    当然,如果你想进入到catch块,那返回true就可以了。

    嗯。这一段能看明白就行了,这不算是一个常规的解决办法,只能算一个旁门的小技巧。

    三、内建的异常中间件

    内建的异常处理,有两个。

    一个是我们最常见的,在创建webapi类型的工程时,Startup.cs文件中已经默认生成好的:

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

    这个app.UseDeveloperExceptionPage就是框架中用于显示异常的详细信息的中间件。

    另一个,是app.UseExceptionHandler,也是一个内置的用来处理异常的中间件,可以这样用:

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

    参数可以是一个Endpoint,也可以是一个Action。实际应用时,还可以写成一个IApplicationBuilder的扩展。

    四、自定义的中间件

    如果对异常管理有很高的要求,自定义异常处理中间件,是最合适的一种方式。

    中间件的写法,我在前文一文说通Dotnet Core的中间件中有详细的说明,这儿不再多说。

    给一段例子看看:

    public class CustomExceptionMiddleware {private readonly RequestDelegate _next;private readonly ILogger<CustomExceptionMiddleware> _logger;public CustomExceptionMiddleware(RequestDelegate next, ILogger<CustomExceptionMiddleware> 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

    喜欢就来个三连,让更多人因你而受益

    总结

    以上是生活随笔为你收集整理的Dotnet Core异常处理的优雅实践的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。