2008-11-27 102 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(); 

这样你得到你所概述,而不必从一个特定的基异常,它允许你扔你喜欢的任何异常继承的好处。框架中有几个地方在内部使用这种方法。请注意,我倾向于不把工厂方法放在具体的异常上,因为它们显示在派生类上,可以得到。

相关问题