创建自定义异常类的原因是——至少对我而言——我需要传输额外的信息,例如一些域对象。
为了实现这一点,我向我的异常类添加了一个只读属性,并提供了一个初始化这个属性并只允许非空值的构造函数。
现在,根据MSDN和代码分析,每个 Exception 类型都应该至少有四个特定的构造函数。
最终结果是可以创建没有我的自定义属性集的自定义异常类的实例。
这有两个问题:
- 每个异常处理程序都必须检查该属性是否
null
- 如果没有该附加属性,某些异常处理程序将无法做任何有用的事情。
如何解决这个困境?
你能为你的域对象提供一个默认值吗,也许是一个空对象?( http://en.wikipedia.org/wiki/Null_Object_pattern ) 这样,您的任何异常处理程序都不需要更聪明。当使用域对象的任何方法或属性时,让域对象的 Null Object 实例不执行任何操作。
另一种选择是使用 [SuppressMessage] 来避免代码分析消息,然后没有零参数的构造函数。那么问题就变成了你的类不再是可序列化的。这对您来说可能是也可能不是问题。
最后,考虑创建一个中间类,将其命名为 DomainObjectExceptionHandler。它负责在发生异常时处理:
public abstract class DomainObjectExceptionHandlerBase {
public abstract void HandleException();
}
然后有一个实现知道当一个真正的域对象发生异常时该怎么做:
public class DomainObjectExceptionHandler : DomainObjectExceptionHandlerBase {
private DomainObject domainObject;
public DomainObjectExceptionHandler(DomainObject domainObject) {
this.domainObject = domainObject;
public override void HandleException() {
// do real recovery work with the domain object
}
}
然后是一个什么都不做的空对象:
public class NullDomainObjectExceptionHandler : DomainObjectExceptionHandlerBase {
public override void HandleException() {
// do nothing
}
}
现在您的异常类可以具有四个推荐的签名,包括:
public class DomainObjectException {
public DomainObjectException() {
this.Handler = new NullDomainObjectExceptionHandler();
}
public DomainObjectException(DomainObject domainObject) {
this.Handler = new DomainObjectExceptionHandler(domainObject);
}
public DomainObjectExceptionHandlerBase Handler { get; private set; }
}
您的抛出代码如下所示:
if (domainObject.IsUnhappy())
throw new DomainObjectException(domainObject);
您的异常处理程序如下所示:
try {
FrobulateDomainObjects();
} catch (DomainObjectException ex) {
ex.Handler.HandleException();
}
注意异常处理程序不需要知道 DomainObject 的存在,它将它委托给 DomainObjectExceptionHandler。