使用DataContractSerializer进行简单的数据文件版本控制

Rom*_*kov 6 .net datacontractserializer

阅读数据合同版本后,我们得出的结论是,它并非真正的全部故事.例如,如果您曾经拥有ValueA会发生什么,而在新版本中它现在称为ValueB并且属于不同类型,您需要将ValueA转换为ValueB吗?

我可以使用一些回调来帮助解决这个问题,但如果我们希望格式在很长一段时间内频繁更改,它看起来就不是一个非常易于维护的解决方案.

我们解决的解决方案是保留"按版本保存"字段,并在加载文件时根据需要调用特定于旧版本的转换例程.这些转换例程知道如何将旧数据的XML转换为XML以获取更新的数据.

但是,事实证明,DataContractSerializes要求元素的顺序完全符合预期.这意味着我们的转换过程必须知道元素插入恰好在正确的位置.如果考虑继承,这比简单地添加具有已知名称的元素要困难得多.对于继承,您不能可靠AddBeforeSelfAddAfterSelf 任何字段,因为没有一个字段始终位于此新字段旁边.

撇开DataContractSerializer如此严格的原因,你能否提出解决方法?也许是一篇关于如何与非常旧的数据合同保持向后兼容的好文章,在你对格式进行第100次重大更改时不会变得笨拙.

有一些额外的指南这篇文章,但必须用于不同的目的已经被写入.例如,我们无法让旧的数据成员永远留下来(第9点).看起来大多数这样的文章是从通信协议的角度编写的,而不是将数据存储在文件中.

Rom*_*kov 5

一年后我不得不说这DataContractSerializer对于版本控制来说真的很糟糕。它太僵化了。它实际上适用于不太可能改变的合同,并且仅以特定方式改变。您必须做额外的工作才能使用它,只是为了使其更快 - 例如 KnownTypeAttribute。我只会在您需要相对快速的序列化时才推荐它 - 可以说,这对于它的设计目的相当重要。

我从事的另一个项目使用更灵活的序列化器,例如,它不会跳过调用类构造函数(某些事情造成了很多不便),并且不要求项目按特定顺序排列。它优雅地处理新字段(它们保留在构造函数设置的任何位置)并在零程序员干预的情况下删除字段。

现在,如果我可以将其发布在这里就好了……但是它比 DataContractSerializer 慢大约 5 倍到 10 倍。


Joe*_*Joe 3

我认为您对内置版本控制支持的期望过高。它的真正目的是允许您添加新成员,同时保留所有现有功能和成员。

在对合同进行重大更改的情况下,您可能最好创建合同的新版本(例如使用新的命名空间 - 常见的约定是使用后缀 yyyy/mm,例如http://mycompany.com /myservices/2009/10)。

然后,您需要能够支持尽可能多的旧合约,并且需要能够在每个受支持的合约和您正在使用的任何当前内部表示之间进行转换。