.NET:異常處理的兩條「黃金定律」,求批!

背景

架構之處必須考慮:如何處理異常?如何定義本身的異常體系?本文爲了強化這個概念而寫。架構

異常處理的兩條「黃金定律」

本身抄襲的兩條規律:app

  1. 異常不能穿過「邊界類」。
  2. 異常不能在沒有恢復的狀況下「吞掉」。

咱們會將異常分爲兩類:「須要恢復」和「不須要恢復」,「須要恢復」的異常若是到達了邊界類,就說明系統有BUG了,這類異常須要記錄到日誌。「不須要恢復」的異常須要進一步分爲:「咱們不能恢復」和「咱們不指望恢復」,若是這類異常到達邊界類,「咱們不能恢復「的異常一樣須要記錄到日誌,「咱們不指望恢復」的異常則直接將異常信息顯示給界面。通常採用AOP處理邊界異常。ide

示例

AOPspa

 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。日誌

相關文章
相關標籤/搜索