更具体地说,当异常包含自定义对象时,这些对象本身可能是可序列化的,也可能不是。

举个例子:

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。

是否有通用的代码模式来实现自定义异常的序列化?


当前回答

实现ISerializable,并遵循执行此操作的常规模式。

您需要用[Serializable]属性标记类,并添加对该接口的支持,还需要添加隐含的构造函数(在该页上有描述,搜索暗示构造函数)。您可以在文本下面的代码中看到它的实现示例。

其他回答

用[Serializable]标记类,尽管我不确定序列化器将如何处理IList成员。

EDIT

下面的帖子是正确的,因为你的自定义异常有接受参数的构造函数,你必须实现ISerializable。

如果使用默认构造函数,并使用getter/setter属性公开两个自定义成员,则只需设置属性即可。

实现ISerializable,并遵循执行此操作的常规模式。

您需要用[Serializable]属性标记类,并添加对该接口的支持,还需要添加隐含的构造函数(在该页上有描述,搜索暗示构造函数)。您可以在文本下面的代码中看到它的实现示例。

在. net Core中,. net 5.0及以上版本不使用Serializable,因为微软遵循在BinaryFormatter中发现的安全威胁实践。

使用存储在数据集合中的示例

曾经有一篇来自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]属性标记它们,这更像是文档,因为您自己实现了序列化。

我不得不认为,想要序列化一个异常强烈地表明您对某些事情采取了错误的方法。这里的终极目标是什么?如果在两个进程之间传递异常,或者在同一个进程的不同运行之间传递异常,那么异常的大多数属性在另一个进程中是无效的。

在catch()语句中提取所需的状态信息并将其存档可能更有意义。