緣由
當我們開發應用程式時,難免(一定)會有bug。無論是使用者輸入不正確的資料,環境/平台因素等,只要有 bug 就是開發人員的錯。
開發人員難道只有被罵的份嗎?當然不能坐以待斃。我們開發人員必須留下錯誤的痕跡,以快速地找到錯誤的原因。
因此,我們都必須寫像下面的 Code
try { //執行商業邏輯 } catch (Exception) { //記錄例外資訊到檔案或資料庫 Console.WriteLine("對不起!發生錯誤,請洽..."); }
要如何進行例外的記錄(log)呢?
解決1:使用 EHAB
解決的方法,我都是使用 Enterprise Library 中的Exception Handling Application Block。
程式碼的部份很簡單。只需要呼叫ExceptionPolicy.HandleException 如下:
public virtual void Go2() { try { throw new NotImplementedException(); } catch (Exception ex) { ExceptionPolicy.HandleException(ex, "Policy"); } }
但config 設定的話,新手初看就很複雜了。這裡我並不想多做介紹,有興趣的話可以看這一篇。
這裡有個問題,如果每一段程式都需要 try…cache 再來處理例外的話,程式碼就變的很難看。
解決2:集中一個地方處理例外
要在同一個地方處理例外其實很常見。例如在 ASP.NET 上可以在 Global.aspx.cs 中的 Application_Error 中處理
protected void Application_Error(object sender, EventArgs e) { //處理 Application 所有拋出的 exception Exception exception = Server.GetLastError(); ExceptionPolicy.HandleException(exception, "LogAllInFile"); }
雖然集中在一個地方處理很方便,但能做的事情也很有限,只能使用相同的 Policy 來處理例外。並且一旦到如 Global.asax 這裡來處理時,就失去了各自處理的彈性。
有沒有一個方便的解決方法,既可以各自處理,又不用每個地方寫 try..cache 這樣的 Code 呢?
解決3:使用 ExceptionCallHandler
接下來就是今天的主題了。PIAB 可以幫我們解決這樣的問題。第一步,是要讓物件可以被注入。因此物件的類別宣告不可以為sealed,Method 也必須是 virtual。
public class Go { public virtual void Go1() { throw new NotImplementedException(); }
第二步是在 Method 上進行 Attribute 的註記。如下:
[ExceptionCallHandler("Policy")] public virtual void Go1() { throw new NotImplementedException(); }
其中,”Policy”是Exception Policy 的名稱。
當然,不是只有這樣就可以搞定的。我們必須在實例化物件前開始進行複雜的 injection(注射)以達到我們的目的。第三步:
static void Main(string[] args) { var container = new UnityContainer(); container.AddNewExtension<EnterpriseLibraryCoreExtension>(); container.AddNewExtension<Interception>(); container.RegisterType<ICallHandler, ExceptionCallHandler>("ExceptionCallHandler", new InjectionConstructor( new ResolvedParameter(typeof(ExceptionPolicyImpl), "Policy"))); container.RegisterType<Go>( new InterceptionBehavior<PolicyInjectionBehavior>(), new Interceptor<VirtualMethodInterceptor>()); var g = container.Resolve<Go>(); g.Go1(); }
討論
使用 ExceptionCallHandler 來解決似乎方便多了,因為可以在不同的 Method 上註記當錯誤發生時,使用不同的 exception policy 處理之。
但壞處是物件的 Method 必須都是 virtual,讓 IoC 有機會注入不同的行為。
沒有留言:
張貼留言