更具体地说,当异常包含自定义对象时,这些对象本身可能是可序列化的,也可能不是。
举个例子:
public class MyException : Exception
{
private readonly string resourceName;
private readonly IList<string> validationErrors;
public MyException(string resourceName, IList<string> validationErrors)
{
this.resourceName = resourceName;
this.validationErrors = validationErrors;
}
public string ResourceName
{
get { return this.resourceName; }
}
public IList<string> ValidationErrors
{
get { return this.validationErrors; }
}
}
如果这个异常被序列化和反序列化,两个自定义属性(ResourceName和ValidationErrors)将不会被保留。属性将返回null。
是否有通用的代码模式来实现自定义异常的序列化?
异常已经是可序列化的,但是您需要重写GetObjectData方法来存储变量,并提供一个构造函数,可以在重新水化对象时调用该构造函数。
所以你的例子就是:
[Serializable]
public class MyException : Exception
{
private readonly string resourceName;
private readonly IList<string> validationErrors;
public MyException(string resourceName, IList<string> validationErrors)
{
this.resourceName = resourceName;
this.validationErrors = validationErrors;
}
public string ResourceName
{
get { return this.resourceName; }
}
public IList<string> ValidationErrors
{
get { return this.validationErrors; }
}
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter=true)]
protected MyException(SerializationInfo info, StreamingContext context) : base (info, context)
{
this.resourceName = info.GetString("MyException.ResourceName");
this.validationErrors = info.GetValue("MyException.ValidationErrors", typeof(IList<string>));
}
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter=true)]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("MyException.ResourceName", this.ResourceName);
// Note: if "List<T>" isn't serializable you may need to work out another
// method of adding your list, this is just for show...
info.AddValue("MyException.ValidationErrors", this.ValidationErrors, typeof(IList<string>));
}
}
曾经有一篇来自Eric Gunnerson在MSDN上的优秀文章“脾气暴躁的例外”,但它似乎已经被撤下了。URL是:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp08162001.asp
Aydsman的答案是正确的,更多信息在这里:
http://msdn.microsoft.com/en-us/library/ms229064.aspx
我想不出带有不可序列化成员的Exception的任何用例,但如果您避免尝试在GetObjectData和反序列化构造函数中序列化/反序列化它们,应该是可以的。还要用[NonSerialized]属性标记它们,这更像是文档,因为您自己实现了序列化。