版本化序列化文件

时间:2009-03-25 21:19:28

标签: c# design-patterns serialization

我有一个工作应用程序将文档(IDocument类型)序列化到磁盘。从那里开始有另一个我可以打开该文档的应用程序(IDocument实现IPrintDocument)供查看。

我们假设我已经将一个IDocument写入磁盘,然后一周后,一个字段被添加到IDocument对象中。编写文件的程序和打开它们的程序都使用IDocument的这个新“版本”进行更新。在尝试打开之前的IDocument版本时,它会破坏(我假设 - 没有机会检查,我在这里展望)。是否有一种已知的模式可以缓解这种问题?

3 个答案:

答案 0 :(得分:4)

是 - 使用tolerant to versioning的序列化机制。

可以预见,我将建议使用Google's Protocol Buffers,其中至少有two viable .NET实现。只要你小心,协议缓冲区都是向后兼容的 - 你可以用旧代码读取新消息,反之亦然,旧代码仍然可以保留它不理解的信息。

另一种选择是XML,无论是否使用.NET的内置XML序列化。据我所知,内置序列化在版本控制方面并不是特别灵活。

答案 1 :(得分:3)

.net内置序列化是一个选项,但它确实要求您在将来要扩展的特定部分上添加占位符。

您可以为额外的元素/属性添加占位符,如下面的代码:

[XmlAnyElement()]
public XmlElement[] ExtendedElements { get; set; }
[XmlAnyAttribute()]
public XmlAttribute[] ExtendedAttributes { get; set; }

通过在所涉及的类中添加上述内容,您可以有效地读取已保存的具有额外元素/属性的信息,修改软件知道如何处理和保存的常规属性。这允许向后和向前兼容。添加新字段时,只需添加所需的属性。

请注意,上述内容仅限于在指定的钩子中扩展。

更新:正如Jon在评论中提到的,上面只适用于xml序列化。据我所知,二进制序列化不支持类似的东西。在二进制序列化中,您可以获得应用程序的旧版/新版本以便能够读取彼此的序列化信息(.net 2.0+),但是如果将其保存回来,则会丢失版本无法处理的额外信息。

从.net 2.0开始,反序列化过程忽略了额外的数据,如果将其与可选字段组合,则可以有效地使两个应用程序读取其他版本的格式。问题是数据不像xml字段那样由类保存。

一些相关链接:http://msdn.microsoft.com/en-us/library/system.runtime.serialization.serializationbinder.aspxhttp://msdn.microsoft.com/en-us/library/ms229752.aspx

如果你不想要xml序列化,我会选择Jon的方法。

聚苯乙烯。我不知道是否有一些好的第三方实现,我们可以访问,扩展二进制序列化来保存和保存额外的数据。

答案 2 :(得分:1)

内置序列化应该使用[OptionalField]属性为版本更新提供最小容差。但事情可以get tricky really fast,所以你最好看看使用解决这些问题的框架,如Jons protobuffers等......

另外两个选项是为文档存储使用Sqlite之类的嵌入式数据库。并手动(或使用ORM)将对象中的属性/字段映射到表中的列。

使用Lucene也可以通过文档全文搜索。