2013年10月13日 星期日

MS Enterprise Library 6.0 (三) - Exception Handling Application Block

有時候心情好,忍不住就多寫幾篇Blog。(當然,心情比較差的時候,可能十天半個月沒辦法安安靜靜的把一些東西整理出來)

前面錄了兩段Enterprise Library的介紹影片,分別談了Unity Application BlockLogging Application Block,這一篇緊接著談Exception Handling Application Block。

由於時空的限制,我現在所在的位置沒法錄製影片,所以只好乖乖用寫的了。

如果可以讓我選擇,我喜歡錄影片遠超過寫文字,原因很簡單,因為我話多,blog有時候忍不住就多寫了幾百字,但這年頭大家都不看字的,害我覺得寫了很無聊。寫了沒人看不打緊,花的時間很多,年紀大了越來越懶,用講的比較快,還可以當作上課的彩排甚至教材,所以我喜歡錄影遠超過寫文章。

岔題了。

Exception Handling Application Block,顧名思義就是系統中處裡例外的模塊,大家都知道,我們會在程式碼中加上try...catch來處理例外,程式碼常常會像是這樣:
            try
             {
                 int a = 10, b = 0;

                 a = a / b;
                 Console.WriteLine("done!");
                 Console.ReadKey();
             }
             catch (Exception ex)
             {
               //如果發生例外...就...
             }
這樣的程式碼沒啥太大的問題(除了因為是範例所以一定會發生例外之外...)。

但如果像上面這樣的程式碼一多,我們就會發現,每一個try...catch裡面都是另一段不受管理的複雜的錯誤處裡邏輯,可能是寫log、可能是發mail、可能是retry...,不僅如此,一旦例外處理區塊寫死之後,例外處理區塊常常本身就是一個大累贅。

還有,發生例外的可能性和類型很多元,上面這段程式碼非常簡單,只可能得到一個 "除以零" 錯誤。但真實世界中,如果是一段比較複雜的程式碼,有網路連線、有檔案處理、有數字計算、日期計算...而我們要針對可能發生的不同的例外分開來處理(例如發生檔案相關錯誤就發mail、發生網路錯誤就寫file log,發生其他運算錯誤就寫event log...,那你的catch中的程式碼就精彩了!!!
             try
             {
                 //如果這邊很長,或是進行了各種不同的動作             }
             catch (Exception ex)
             {
                 //如果是DivideByZeroException
                 if (ex.GetType().Equals(typeof(System.DivideByZeroException)))
                 {
                     //...
                 }
                 //如果是WebException
                 if (ex.GetType().Equals(typeof(System.Net.WebException)))
                 {
                     //...
                 }
                 //如果是FileLoadException
                 if (ex.GetType().Equals(typeof(System.IO.FileLoadException)))
                 {
                     //...
                 }
             }
所以可以想見,當我們在真實世界的專案當中,catch部分可能要針對各種不同型態的例外,進行各種不同的處理,再加上又要考慮是否rethrow,複雜度又更高了...

也因此,我們需要一個一致性的例外管理模塊,這時候, Exception Handling Application Block 就可以派上用場了。Exception Handling Application Block 可以做到:


  1. 用統一的程式碼來管理例外
  2. 透過設定App.Config來處理例外,如此一來若要改變例外處理的方式,就可以不用改程式碼
  3. 可針對不同類型的例外設定不同的處裡方式
  4. 可隨時增加或減少某種例外的處理方式(例如發生例外時的紀錄本來只有發email,但要改成同時寫入db,可以透過設定的方式來進行)
知道了用途之後,我們就來看看實際上怎麼用。

Step1:現在專案中加入:
  1. Exception Handling Application Block
  2. Exception Handling Application Block Logging Handler
  3. Logging Application Block

本來我們只需要加入第1個,但因為我們處理Exception的方法是寫Log,因此也加入了2,3



Step2:請參考底下的程式碼:
底下這段程式碼是Console Application,基本上3-10行是Enterprise Library的相關程式碼,主要是從設定檔來建立所需要的各種物件。(待會會教大家如何建立設定檔)
16行是會觸發一個除以零錯誤的代碼
而23,24則是我們的核心了,我們透過ExceptionPolicy這個 enterprise library的錯誤處理類別,來處理錯誤,採用的是名稱為Policy的設定檔內容。

-------------------------------------------------
static void Main(string[] args)
{
    //抓取Config檔案中的設定,作為configurationSource 
    IConfigurationSource configurationSource = ConfigurationSourceFactory.Create();
    //以Config檔案中的設定,建立logWriterFactory 
    LogWriterFactory logWriterFactory = new LogWriterFactory(configurationSource);
    //以Config檔案中的設定,建立LogWriter
    Logger.SetLogWriter(logWriterFactory.Create());
    //以Config檔案中的設定,建立ExceptionManager
    ExceptionPolicy.SetExceptionManager(new ExceptionPolicyFactory(configurationSource).CreateManager(), true);
    //故意寫一段會錯的程式碼
    try
    {
        int a = 10, b = 0;

        a = a / b;
        Console.WriteLine("done!");
        Console.ReadKey();
    }
    catch (Exception ex)
    {
        //以Config檔案中的 "Policy" ExceptionPolicy設定來處理
        var rethrow = ExceptionPolicy.HandleException(ex, "Policy");
        //如果設定檔說要重丟例外,就重丟
        if (rethrow) throw;
    }
}
--------------------------------------------------------

OK,所以瞭解了程式碼之後,就知道關鍵在名稱為Policy的設定檔內容,這個設定檔的內容決定了我們要如何處理、以及要處理哪些類型的例外,並且決定了處裡完例外之後,是否要重新丟出例外。

知道了之後,我們就來看如何建立這個設定檔,請參考底下的影片,我們的動作是:

  1. 從VS2012開啟設定檔編輯器
  2. 建立Exception Handling Settings( 注意名稱為 Policy,且post HandlingAction設為None )
  3. 建立Logging Exception Handler(配合Exception Handling Settings)
  4. 在Logging Exception Handler中,指定Logging Settings( 注意名稱為 General )
  5. 建立Rolling Flat File Trace Listener


最後,我們來看執行結(請留意,當修改了設定檔之後重新執行,你會發現程式對錯誤的處裡方式也隨著設定檔而蓋變了):

btw,   請原諒我只能很扼要的介紹Enterprise Library中的exception handling application block,其他更多精彩的功能,請自行參考微軟Enterprise Library網站囉。

2 則留言:

匿名 提到...

董老師您好,謝謝您的分享。其實無論您用什麼方式分享技術、工作心得或心情,我每每都有得到收獲,我相信有關注您文章的人都有類似的感受。

再次感謝您。

C.K. Hsieh

David 提到...

多謝你的支持~ :)