.NET:异常处理的两条“黄金定律”,求批!

背景

架构之处必须考虑:如何处理异常?如何定义自己的异常体系?本文为了强化这个概念而写。

异常处理的两条“黄金定律”

自己抄袭的两条规律:

  1. 异常不能穿过“边界类”。
  2. 异常不能在没有恢复的情况下“吞掉”。

我们会将异常分为两类:“需要恢复”和“不需要恢复”,“需要恢复”的异常如果到达了边界类,就说明系统有BUG了,这类异常需要记录到日志。“不需要恢复”的异常需要进一步分为:“我们不能恢复”和“我们不期望恢复”,如果这类异常到达边界类,“我们不能恢复“的异常同样需要记录到日志,“我们不期望恢复”的异常则直接将异常信息显示给界面。一般采用AOP处理边界异常。

示例

AOP

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Web.Mvc;
 7 
 8 using Common.Logging;
 9 using Happy.ExceptionHanding;
10 using Happy.Web.Mvc.Newtonsoft;
11 
12 namespace Happy.Web.Mvc.ExceptionHanding
13 {
14     /// <summary>
15     /// 处理应用程序未捕获的异常。
16     /// </summary>
17     [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
18     public class WriteExceptionResultAttribute : FilterAttribute, IExceptionFilter
19     {
20         /// <inheritdoc />
21         public void OnException(ExceptionContext filterContext)
22         {
23             var exception = filterContext.Exception;
24             if (!FriendlyExceptionRegistry.IsFriendly(exception.GetType()))
25             {
26                 LogManager.GetCurrentClassLogger().Error(exception);
27             }
28             filterContext.Result = CreateErrorResult(exception);
29             filterContext.ExceptionHandled = true;
30         }
31 
32         private static ActionResult CreateErrorResult(Exception exception)
33         {
34             var information = ExceptionInformationProviderRegistry.CreateInformation(exception);
35 
36             return new NewtonsoftJsonResult
37             {
38                 Data = information
39             };
40         }
41     }
42 }
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 using Happy.ExtentionMethods;
 8 
 9 namespace Happy.ExceptionHanding
10 {
11     /// <summary>
12     /// 异常信息提供者注册处。
13     /// </summary>
14     public static class ExceptionInformationProviderRegistry
15     {
16         private static readonly Dictionary<Type, IExceptionInformationProvider> _providers
17             = new Dictionary<Type, IExceptionInformationProvider>();
18 
19         /// <summary>
20         /// 注册提供者。
21         /// </summary>
22         public static void Register<TException>(IExceptionInformationProvider provider)
23             where TException : Exception
24         {
25             Register(typeof(TException), provider);
26         }
27 
28         /// <summary>
29         /// 注册提供者。
30         /// </summary>
31         public static void Register(Type exceptionType, IExceptionInformationProvider provider)
32         {
33             exceptionType.MustNotNull("exceptionType");
34             provider.MustNotNull("provider");
35 
36             _providers[exceptionType] = provider;
37         }
38 
39         public static Dictionary<string, object> CreateInformation(Exception exception)
40         {
41             exception.MustNotNull("exception");
42 
43             var exceptionType = exception.GetType();
44 
45             var information = CreateDefaultInformation(exception);
46 
47             if (_providers.ContainsKey(exceptionType))
48             {
49                 var extInformation = _providers[exceptionType].CreateInformation(exception);
50 
51                 foreach (var item in extInformation.ToDictionary())
52                 {
53                     information[item.Key] = item.Value;
54                 }
55             }
56             else
57             {
58                 if (FriendlyExceptionRegistry.IsFriendly(exception.GetType()))
59                 {
60                     information["exception"] = Resource.Messages.Msg_DefaultExceptionMessage;
61                 }
62             }
63 
64             return information;
65         }
66 
67         private static Dictionary<string, object> CreateDefaultInformation(Exception exception)
68         {
69             return new Dictionary<string, object> 
70             { 
71                 { "success", false },
72                 { "exception", exception.GetType().Name },
73                 { "message",exception.Message }
74             };
75         }
76     }
77 }

备注

放弃继续玩 GO 的一个原因就是:GO 的异常处理太不爽了,或者是我自己的原因,不够 OPEN。

原文地址:https://www.cnblogs.com/happyframework/p/3381676.html