猿问

使自定义.NET Exception可序列化的正确方法是什么?

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


举个例子:


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; }

    }

}

如果将此Exception序列化和反序列化,则将不保留两个自定义属性(ResourceName和ValidationErrors)。属性将返回null。


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


三国纷争
浏览 642回答 3
3回答

波斯汪

异常已经可以序列化,但是您需要重写该GetObjectData方法来存储变量并提供一个构造函数,该构造函数可在重新为对象补水时调用。因此,您的示例变为:[Serializable]public class MyException : Exception{&nbsp; &nbsp; private readonly string resourceName;&nbsp; &nbsp; private readonly IList<string> validationErrors;&nbsp; &nbsp; public MyException(string resourceName, IList<string> validationErrors)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; this.resourceName = resourceName;&nbsp; &nbsp; &nbsp; &nbsp; this.validationErrors = validationErrors;&nbsp; &nbsp; }&nbsp; &nbsp; public string ResourceName&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; get { return this.resourceName; }&nbsp; &nbsp; }&nbsp; &nbsp; public IList<string> ValidationErrors&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; get { return this.validationErrors; }&nbsp; &nbsp; }&nbsp; &nbsp; [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter=true)]&nbsp; &nbsp; protected MyException(SerializationInfo info, StreamingContext context) : base (info, context)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; this.resourceName = info.GetString("MyException.ResourceName");&nbsp; &nbsp; &nbsp; &nbsp; this.validationErrors = info.GetValue("MyException.ValidationErrors", typeof(IList<string>));&nbsp; &nbsp; }&nbsp; &nbsp; [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter=true)]&nbsp; &nbsp; public override void GetObjectData(SerializationInfo info, StreamingContext context)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; base.GetObjectData(info, context);&nbsp; &nbsp; &nbsp; &nbsp; info.AddValue("MyException.ResourceName", this.ResourceName);&nbsp; &nbsp; &nbsp; &nbsp; // Note: if "List<T>" isn't serializable you may need to work out another&nbsp; &nbsp; &nbsp; &nbsp; //&nbsp; &nbsp; &nbsp; &nbsp;method of adding your list, this is just for show...&nbsp; &nbsp; &nbsp; &nbsp; info.AddValue("MyException.ValidationErrors", this.ValidationErrors, typeof(IList<string>));&nbsp; &nbsp; }}

BIG阳

为了补充上面的正确答案,我发现如果将自定义属性存储在类的Data集合中,则可以避免执行此自定义序列化工作Exception。例如:[Serializable]public class JsonReadException : Exception{&nbsp; &nbsp; // ...&nbsp; &nbsp; public string JsonFilePath&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; get { return Data[@"_jsonFilePath"] as string; }&nbsp; &nbsp; &nbsp; &nbsp; private set { Data[@"_jsonFilePath"] = value; }&nbsp; &nbsp; }&nbsp; &nbsp; public string Json&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; get { return Data[@"_json"] as string; }&nbsp; &nbsp; &nbsp; &nbsp; private set { Data[@"_json"] = value; }&nbsp; &nbsp; }&nbsp; &nbsp; // ...}就性能而言,这可能比Daniel提供的解决方案效率低,并且可能仅适用于“整数”类型,例如字符串和整数等。对于我来说,这仍然是非常容易并且可以理解的。
随时随地看视频慕课网APP
我要回答