C#XML序列化向后兼容性

时间:2014-08-14 16:46:42

标签: c# xml serialization backwards-compatibility xml-deserialization

以前,序列化/反序列化方法使用类型Item

public class Item{}

现在我有了一个名为ItemWrapper的新类,它来自Item,附加了一个属性:

public class ItemWrapper : Item
{
    public string NewProperty { get; set; }
}

现在我的序列化/反序列化方法使用类型ItemWrapper。现在我已经破坏了向后兼容性。我无法加载任何在旧版本中保存的Item类型的XML文件。当我尝试将Item反序列化为ItemWrapper时,我考虑在反序列化方法上设置try / catch,然后在catch中尝试将反序列化为Item。或者我可以通过xPath查看XML结构,如果找不到ItemWrapper,我可以将其视为Item。这两种解决方案都让人觉得难以理解,而且我确信这是处理这种情况的更好方法。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

好问题。首先,通过派生扩展类是很好地遵循开放/封闭原则,如果Item的所有消费者现在都使用ItemWrapper,那么你实现派生类就没有多少工作量。如果ItemWrapper现在是唯一使用的具体化,那么将其新属性与Item合并并完成。

如果您需要保持两种具体结果,则需要使用一些属性修饰ItemWrapper,以指示XMLSerializer应如何转换为XML字符串和从XML字符串转换。可以找到有关XML属性的信息here

特别要提醒您注意XmlTypeAttribute。这装饰了ItemWrapper类本身,并告诉XmlSerializer使用特定的命名空间和类型名称,而不是根据类名自动生成它们。您可以使用它来使ItemWrapper与通过序列化Item创建的XML文件兼容,方法是声明ItemWrapper类应该创建并使用标记为<Item>的XML序列化。但是,Item(如果它仍然存在)在尝试反序列化通过序列化ItemWrapper创建的文件时将失败,因此此解决方案不能转发 - 兼容,因此以前的版本你的软件如果你没有强有力地处理序列化错误,那么在给出新文件的时候会因为没有明显的原因而死于火热

出于这个原因,在序列化中实现某种版本控制方案通常是个好主意。它可以像您的类型上的public readonly属性一样简单,可以使用XmlAttribute属性进行标记,告诉XmlSerializer将<Item>标记构造为<Item xmlVersion="1.0.0">。如果您已经完成了这一操作,那么ItemWrapper可以覆盖该字段以返回&#34; 1.1.0&#34;,允许XML文件易于区分,因此允许您检查不兼容的文件版本XmlTextReader,如果文件是由更高版本的软件生成的,则会正常返回错误。