一個讓人遺忘的角落—Exception(二)

作者: James.Ying  來源: 博客園  發布時間: 2009-04-21 16:36  閱讀: 1660 次  推薦: 0   原文鏈接   [收藏]  
摘要:現在網站一般都采用多層開發,多層開發的時候,我們應該在哪里處理異常、在拋出異常呢?微軟的意見是類庫的開發人員盡量不要處理異常,類庫的編寫應該按照正常的邏輯去編寫

  在上一篇中"一個被人遺忘的角落"中,跟大家簡單介紹了一下Exception,也使大家充分的了解了Exception管理在一個項目中的重要性,那如何在我們的項目中處理異常呢?因為我從事的是Web開發,所以我只跟大家討論Web的解決方案,Win的解決方式,還希望同大家一起探討。

  上一章中我們了解了異常發生的原因,同時也說了不存在沒有bug的程序,任何網站都會遇到各種各樣的問題,無論是大網站還是小網站都會存在,但大公司和小公司對待異常的態度全然不同,一個是主動出擊,一個是守株待兔,我們是好的開發者,我們不能坐以待斃,我們必須主動出擊。好了,廢話少說,切入主題。

  現在網站一般都采用多層開發,多層開發的時候,我們應該在哪里處理異常、在拋出異常呢?微軟的意見是類庫的開發人員盡量不要處理異常,類庫的編寫應該按照正常的邏輯去編寫,當然也有例外,注意事項可以參見"設計異常解決方案的幾點注意事項 ",好的,按照規范,我們應該盡量在高層進行捕捉和處理,那我們該怎么捕捉,捕捉后怎么處理,捕捉哪些異常呢?雖然微軟提供了很多系統異常,但是這些異常只是負責拋出相關的信息,并沒有為記錄下來,或者出現高級異常的時候,及時通知我們,這樣的做法還是守株待兔,我們還是應該主動的對其進行處理。好在微軟讓我們可以自由的創建自定義的Exception,最好是設定一個自定義Exception基類,讓你的其他自定義Exception都繼承這個類,以便今后更好的擴展。拋出異常其實是性能消耗很大的操作,但是Richer教父說過,拋出異常的性能和你程序的穩定性相比,就變得非常渺小了。所以我們還是偏向于穩定性。因為處理異常的性能消耗,只是在異常發生時才產生,所以性能方面的問題,我們可以忽略了。(或許這話比較拗口,但相比系統的性能,我更趨向于系統的穩定)

如何創建一個自定義的Exception?

  不得不說微軟考慮的太周到了,要創建一個自定義的Exception是非常簡單的。打開VS,創建一個項目,然后添加一個類,在namespace范圍內,輸入Exception,然后2下Tab,VS就自定幫您創建一個自定義的Exception了。Exception的相關屬性和方法,可以參見MSDN。不過自動創建的Exception都是繼承System.Exception的,按照微軟當初的設想,自定義的異常應該繼承System.ApplicationException (可笑的是,微軟自己都沒有遵守這個約定)。我們設定這個作為我們的Exception基類 MyBaseException。

代碼片斷:

 

[global::System.Serializable]

public class MyBaseException : ApplicationException

{

public MyBaseException() { }

public MyBaseException(string message) : base(message) { }

public MyBaseException(string message, Exception inner) : base(message, inner) { }

protected MyBaseException(

System.Runtime.Serialization.SerializationInfo info,

System.Runtime.Serialization.StreamingContext context)

: base(info, context) { }

} 

 

  這就是一個標準的自定義Exception了,至于其它的自定義Exception,應該根據你的項目來進行相關的定義。

  在進行其他定義之前,我們先來想想,我們捕捉這些Exception之后我們需要做些什么?我們需要知道異常發生的各種信息,所以我們需要Log。Log能方便的讓我們查閱發生的異常及Log的異常信息。Log有很多方式,大概的有以下幾種:

  (1)、文本記錄

  (2)、數據庫記錄

  (3)、系統事件記錄(Trace)

  (4)、第三方組件(Log4Net)

  這幾種方式各有利弊,可以根據項目的需求進行選擇,當然你也可以幾種方式合用,比如我們默認的是文本記錄方式,但是在創建Log時發生了System.IOException時,我們就必須選擇其他的方式進行Log。

Log方式

便捷性

查閱性

安全性

結合性

文本記錄

方便

一般

數據庫記錄

一般

方便

一般

系統事件記錄

復雜

復雜

一般

第三方組件

復雜

一般

一般

  我列舉了幾種方式的利弊,大家可以有條件的選擇。如果你的項目中已經使用第三方組件記錄方式,那我建議您使用它。在我后面的解決方案中,我會利用前2種比較常見的方式相結合。

  Log的目的是為我們開發者提供發生異常的時間、地點、人物、原因,所以我們必須盡可能的詳細地記錄,根據一個Exception獲取信息的方法:

Data

Source

Dates and Times

DateTime.Now

Source of Exception

Exception.Source

Type of Exception

Object.GetType

Exception Message

Exception.Message

Current Method

Reflection.MethodInfo.GetCurrentMethod

Machine Name

Environment.MachineName or Dns.GetHostName

CurrentIP

Dns.GetHostByName("host").AddressList[0].Address

Call Stack

Exception.StackTrace or Environment.StackTrace

OS Information

Environment.OSVersion

Applcation Domain

AppDomain.FriendlyName

Current Assembly

Reflection.Assembly.GetExecutingAssembly

Root Error Cause

Exception.GetBaseException

Chained Exception

Exception.InnerException

Assembly Version

Included in AssemblyName.FullName

Thread ID

AppDomain.GetCurrentThreadId

Thread User

Threading.Thread.CurrentPrincipal

  我們可以根據上面的表格,構建我們自己所需要的Log信息。為了便捷的管理,我們應該采用同一格式,進行Log。這里貼一個我寫的信息格式,以供參考:

 

public static class ExceptionLogFormatHelper
{
public static string ExceptionLogFormatter(Exception ex)
{

StringBuilder sbLog = new StringBuilder("\r\n------------------------------------\r\n");

Exception ochainException = ex;

var currentExceptionIndex = 1;

while (ochainException != null)
{

sbLog.Append("\r\nException " + currentExceptionIndex + " )")

.Append("\r\nException Type:" + ochainException.GetType().FullName)

.Append("\r\nException Source:" + ochainException.Source)

.Append("\r\nException Message:" + ochainException.Message)

.Append("\r\nException Date:" + DateTime.Now)

.Append("\r\nEnvironment Stack:" + System.Environment.StackTrace);

ochainException = ochainException.InnerException;

currentExceptionIndex++;

}

sbLog.Append("\r\n------------------------------------\r\n");

return sbLog.ToString();

}
} 

 

  你也可以根據你自己想要的信息構建這么一個方法。

  這一篇廢話多了點,不過還是有必要了解下。還介紹了自定義異常的創建,日志方式的對比,在下一篇,我將介紹通知、異常處理流程和定義自己的一個MyBaseException。

0
0
 
標簽:Exception
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()