2009-07-08 59 views
5

当自定义异常处理,我通常从Exception继承,然后添加一些字段/属性,我的异常类来存储一些额外的信息:我应该如何将数据存储在自定义异常中?

public class MyException : Exception 
{ 
    public int ErrorCode{get;set;} 

    public MyException() 
    {} 
} 

在上面的例子中,ErrorCode值存储在异常,这意味着如果来自受保护的构造函数中的SerializationInfo对象和重写的GetObjectData方法,我必须将其添加到并退出。

Exception类有一个Data属性,它根据MSDN:

获取一个提供有关异常的用户定义的其他信息的键/值对的集合。

如果我存储Data里面的错误代码,它会得到由异常类我序列化(根据反射器),这意味着我的异常类现在看起来像:

public class MyException : Exception 
{ 
    public int ErrorCode 
    { 
     get {return (int) Data["ErrorCode"];} 
     set {Data["ErrorCode"] = value;} 
    } 

    public MyException() 
    {} 
} 

这意味着尽管在处理错误代码的获取/设置方面还有一些工作要做(例如处理错误代码可能不在字典中的错误代码和错误代码的情况),但我不必担心序列化/将其解串。

这是只有两个达到同样的事情,不同的方式,还是一种方式有什么明显的优势(S)比其他(除了那些我已经提到过)?

回答

1

我会避免使用数据,因为它不受您的控制,例如,某处的某些代码可能会决定覆盖“ErrorCode”值。而是使用propery并实现序列化。我使用下面的代码来测试我所有的自定义异常,以确保我已正确实施它们。

public static void TestCustomException<T>() where T : Exception 
{ 
    var t = typeof(T); 

    //Custom exceptions should have the following 3 constructors 
    var e1 = (T)Activator.CreateInstance(t, null); 

    const string message = "message"; 
    var e2 = (T)Activator.CreateInstance(t, message); 
    Assert.AreEqual(message, e2.Message); 

    var innerEx = new Exception("inner Exception"); 
    var e3 = (T)Activator.CreateInstance(t, message, innerEx); 
    Assert.AreEqual(message, e3.Message); 
    Assert.AreEqual(innerEx, e3.InnerException); 

    //They should also be serializable 
    var stream = new MemoryStream(); 
    var formatter = new BinaryFormatter(); 
    formatter.Serialize(stream, e3); 
    stream.Flush(); 
    stream.Position = 0; 
    var e4 = (T)formatter.Deserialize(stream); 
    Assert.AreEqual(message, e4.Message); 
    Assert.AreEqual(innerEx.ToString(), e4.InnerException.ToString()); 
} 
0

您应该使用第一个解决方案。除非您计划使用附加信息提升行异常实例,否则我无法在Data属性中看到很多值。

如果你有自己的异常类型,然后使用属性,而不是:这是更清洁和安全。

1

Microsoft's own guidelines

不要做出例外序列化。必须序列化异常才能跨应用程序域和远程边界正确工作。

我将其存储在数据财产黯然将让外部的代码修改值未经同意,或使用的解决方案1(在你的例子),但使之可序列化。最后,我可能会去解决方案1,所以我可以肯定,值永远不会改变。

5

如果您费心去创建自己的异常,你不需要数据属性。当您想要在现有的异常类中存储一些额外的信息时,数据非常有用,但不希望创建您自己的自定义异常类。

相关问题