2008-11-27 29 views
1

標題是有點抽象,所以也許更容易與一個具體的例子來解釋:有沒有辦法在對基類構造函數的調用中使用可覆蓋的行爲?

我發現它有用有我的異常類需要一個枚舉參數,而不是字符串消息。

throw new SpecificException(SpecificExceptionCode.ThisThingWentWrong); 

這有幾個原因,其中包括:

  • 我可以encapulate所有的邏輯,在一個地方訪問本地化的字符串資源
  • 我可以很容易地確保我有字符串資源,使所有我的例外消息
  • 檢查單元測試中的正確異常消息更簡單

我想寫這種類型的異常的基類。派生異常類通常只是想提供自己的System.Resources.ResourceManager,但也可能提供額外的構造函數。麻煩來了,因爲我只能在調用基類構造函數時調用靜態方法。這使我是這樣的:

public abstract class BaseException : ApplicationException 
{ 
    protected static ResourceManager m_resources; 
    public BaseException(System.Enum errorCode, params object[] messageArgs) 
     : base(ProcessError(errorCode, messageArgs)) 
    {} 

    private static string ProcessError(Enum errorCode, params object[] messageArgs) 
    { 
     string errorMessage = m_resources.GetString(errorCode.ToString()); 
     // Handling of messageArgs and trace logging 
     // .... 
     return finalError; 
    } 
} 

public class SpecificException : BaseException 
{ 
    static SpecificException() 
    { 
     m_resources = //.. Get an appropriate resource manager instance 
    } 

    public SpecificException(SpecificExceptionCode errorCode, params object[] messageArgs) 
     : base(errorCode, messageArgs) 
    {} 
} 

這工作,但我不滿意它沒有編譯時暗示,派生類必須提供自己的System.ResourceManager。我想有一個基類,如:

public abstract class BaseException : ApplicationException 
{ 
    protected abstract static ResourceManager Resources{get;} 

    public BaseException(System.Enum errorCode, params object[] messageArgs) 
     : base(ProcessError(errorCode, messageArgs)) 
    {} 

    private static string ProcessError(Enum errorCode, params object[] messageArgs) 
    { 
     string errorMessage = Resources.GetString(errorCode.ToString()); 
     // Handling of messageArgs and trace logging 
     // .... 
     return finalError; 
    } 
} 

...但我不能有一個抽象的靜態方法。有沒有更好的辦法?

回答

0

爲什麼它必須是靜態屬性?您可以使資源正常屬性:

protected abstract static ResourceManager Resources{get;} 

,只是把它留給實施者實現它返回一個靜態對象:

private static ResourceManager resources = .... 

protected override static ResourceManager Resources{get {return resources; }} 
+0

保護覆蓋靜態<--- !!!!!!警報!!!! – leppie 2008-11-27 12:58:09

2

您當前的代碼被打破......只有一個靜電場;最後一個執行勝利的靜態庫存。

重新使用非靜態方法 - 請注意,在構造函數中調用虛擬/抽象方法有點危險 - 具體類尚未初始化,因此覆蓋可能會嘗試使用尚未使用的數據可用。

ResourceManager不能作爲基礎構造函數的參數嗎?如果它們傳遞null,那麼使用合理的默認值......然後,ProcessError將接受ResourceManager等。

public abstract class BaseException : ApplicationException 
{ 
    static ResourceManager defaultManager; 
    static ResourceManager DefaultManager 
    { 
     get 
     { 
      if (defaultManager == null) defaultManager = TODO; // sensible default 
      return defaultManager; 
     } 
    } 

    public BaseException(System.Enum errorCode, params object[] messageArgs) 
     : this(DefaultManager, errorCode, messageArgs) {} 
    public BaseException(ResourceManager resourceManager, System.Enum errorCode, params object[] messageArgs) 
     : base(ProcessError(resourceManager, errorCode, messageArgs)) 
    { } 

    private static string ProcessError(ResourceManager resourceManager, Enum errorCode, params object[] messageArgs) 
    { 
     if (resourceManager == null) throw new ArgumentNullException("resourceManager"); 
     string errorMessage = resourceManager.GetString(errorCode.ToString()); 
     // Handling of messageArgs and trace logging 
     // .... 
     return finalString; 
    } 
} 

和:

: base(errorCode, messageArgs) 
0

爲什麼不能有一個保護的構造函數的資源:不希望提供自己的管理者只需要使用其他構造函數

public class SpecificException : BaseException 
{ 
    static ResourceManager customManager; 
    static SpecificException() 
    { 
     customManager = //TODO - init manager 
    } 
    public SpecificException(SomeEnum errorCode, params object[] messageArgs) 
     : base(customManager, errorCode, messageArgs) 
    { } 
} 

類經理作爲參數?這樣,你的具體例外將不得不通過它。

我傾向於使用工廠方法,而不是這種問題的構造函數。

public static SpecificException SpecificExceptionCodeName() 
{ 
    //Do resource lookup and create Exception 
} 

然後用

throw ExceptionBuilder.SpecificExceptionCodeName(); 

這樣你得到你所概述,而不必從一個特定的基異常,它允許你扔你喜歡的任何異常繼承的好處。框架中有幾個地方在內部使用這種方法。請注意,我傾向於不把工廠方法放在具體的異常上,因爲它們顯示在派生類上,可以得到。

相關問題