阅读Data Contract Versioning后,我们得出的结论是,这不是真的。例如,如果您曾经拥有ValueA会发生什么,而在新版本中它现在称为ValueB并且属于不同类型,您需要将ValueA转换为ValueB吗?
我可以使用一些callbacks来帮助解决这个问题,但如果我们希望格式能够在很长一段时间内频繁更改,它看起来就不是一个非常易于维护的解决方案。
我们解决的解决方案是保留“按版本保存”字段,并在加载文件时根据需要调用特定于旧版本的转换例程。这些转换例程知道如何将旧数据的XML转换为XML以获取更新的数据。
但事实证明,DataContractSerializes requires the order of the elements to be exactly what it expects。这意味着我们的转化过程必须知道将元素插入完全正确的位置。如果考虑继承,这比简单地添加具有已知名称的元素要困难得多。使用继承,您无法可靠地AddBeforeSelf
或AddAfterSelf
任何字段,因为没有一个字段始终位于此新字段旁边。
撇开DataContractSerializer制作如此严格的原因,您能否提出解决方法?也许这是一篇关于如何与非常旧的数据合同保持向后兼容的好文章,在您对格式进行第100次重大更改时不会变得笨拙。
this article中有一些额外的指南,但这必须是出于不同的目的而编写的。例如,我们无法让旧的数据成员永远留下来(第9点)。看来大多数此类文章都是从通信协议的角度编写的,而不是将数据存储在文件中。
答案 0 :(得分:4)
1年后,我不得不说DataContractSerializer
真的很糟糕。它太僵硬了。它真的意味着不太可能改变的合同,然后只有特定的方式。你必须做额外的工作来使它快速 - 例如KnownTypeAttribute。如果你需要相对较快的序列化,我只会推荐它 - 可以说,它对于它的设计非常重要。
我工作的另一个项目使用了一个更灵活的序列化程序,例如,它不会跳过调用类构造函数(某些东西造成了很多不便),并且不要求项目按特定顺序排列。它优雅地处理新字段(它们留在构造函数设置它们的任何地方)并删除了没有程序员干预的字段。
现在,如果我只能将它发布在这里......但它比DataContractSerializer慢约5x-10x。
答案 1 :(得分:2)
我认为您对内置版本控制支持的期望过高。它的确允许您添加新成员,同时保留所有现有功能,因此保留成员。
在违反合同变更的情况下,您可能更好地创建新版本的合同(例如,使用新的命名空间 - 常见的惯例是使用后缀yyyy / mm,例如{{3} })。
然后,您需要能够支持尽可能多的旧合同,并且需要能够在每个支持的合同与您正在使用的当前内部表示之间进行转换。