架構之處必須考慮:如何處理異常?如何定義本身的異常體系?本文爲了強化這個概念而寫。架構
本身抄襲的兩條規律:app
咱們會將異常分爲兩類:「須要恢復」和「不須要恢復」,「須要恢復」的異常若是到達了邊界類,就說明系統有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。日誌