XmlSerializer:如何反序列化不再存在的枚举值

时间:2012-05-22 18:53:42

标签: c# xml serialization versioning deserialization

我正在使用XMLSerializer将此类保存到文件中。该类有一个字符串和一个枚举,如下所示:

public class IOPoint
{
     string Name {get; set;}
     TypeEnum {get; set;}
}


public enum TypeEnum
{
    Temperature,
    Pressure,
    Humidity,
}

序列化后,它看起来像这样。

<IOPoint>
  <Name>Relative Humidity</Name>
  <TypeEnum>Humidity</TypeEnum>
</IOPoint>

我一直在对这个对象进行序列化和反序列化,几个版本没有任何问题。我不再想支持湿度,所以我将它从枚举中删除了。但是,这会在从XML反序列化时导致异常,因为TypeEnum字段中的值Humidity不是TypeEnum的有效值。这是有道理的,但如何处理呢?

我想做的就是忽略这个错误。并将值保留为null。我已经尝试实现OnUnknownElement XmlDeserilizationEvent类。不幸的是,这并没有发现这个错误。

关于如何捕获并忽略此错误的任何想法(我可以在反序列化完成后清理)。

米奇

4 个答案:

答案 0 :(得分:5)

您可以将成员标记为已过时

public enum TypeEnum
{
    Temperature,
    Pressure,
    [Obsolete]
    Humidity
}

答案 1 :(得分:4)

在您的库已被使用后删除枚举成员通常被认为是不好的做法。为什么不将会员留在原地,但是使用[Obsolete]属性标记以防止将来使用?如果访问标记的成员,则将ObsoleteAttribute(string,bool)构造函数的第二个参数指定为true将导致编译时错误。

public enum TypeEnum
{
    Temperature,
    Pressure,

    [Obsolete("It's always sunny in Philadelphia", true)]
    Humidity,
}

要在检查反序列化值时避免错误,您可以与基础值进行比较:typeEnum == (TypeEnum)2

答案 2 :(得分:2)

您可以使用属性更改节点名称并隐藏xml序列化中的元素,只需手动解析该元素:

public class IOPoint
{
 public string Name {get; set;}

 [XmlIgnore]
 public TypeEnum TypeEnum {get; set;}

 [XmlElement("TypeEnum")]
 public string LegacyTypeEnum 
 {
  get { return this.TypeEnum.ToString(); }
  set 
  { 
   try
   {
    this.TypeEnum = (TypeEnum)Enum.Parse(typeof(TypeEnum),value);
   }
   catch(ArgumentException)
   {
    // Handle "Humidity"
   }
   catch(OverflowException)
   {
   }
  }
 }
}

每条评论似乎都有些混乱; here is a worked example作为Visual Studio 2010项目。这种方法只是手动解析对象的一个​​属性的简单方法(仍然利用XmlSerializer进行XML解析)。

答案 3 :(得分:1)

您可以实现IXmlSerializable,您可以在其中使用类似于TryParse的内容。

但我同意使用Obsolete属性的其他海报。