【发布时间】:2011-01-14 01:58:02
【问题描述】:
我编写了一个可以打开/编辑/保存文档的桌面应用程序。
这些文档由几个不同类型的对象描述,这些对象存储彼此的引用。当然有一个Document 类作为这个数据结构的根。
问题是如何将此文档模型保存到文件中。
我需要什么:
- 支持递归结构。
- 它必须能够打开文件,即使它们是由稍微不同的类生成的。我的用户不想因为我在某处添加了一个字段而在每次发布后重新创建每个文档。
- 它必须处理编译时未知的类(用于插件支持)。
到目前为止我累了什么:
-
XmlSerializer-> 不符合第一个和最后一个条件。 BinarySerializer-> 不符合第二个条件。DataContractSerializer:类似于 XmlSerializer,但支持循环(递归)引用。此外,它的设计考虑了(向前/向后)兼容性:Data Contract Versioning。 [编辑]NetDataContractSerializer:虽然 DataContractSerializer 仍然需要提前知道所有类型(即它不能很好地使用继承),但 NetDataContractSerializer 将类型信息存储在输出中。除此之外,两者似乎是等价的。 [编辑]protobuf-net: 还没来得及试验,不过功能上看起来和DataContractSerializer差不多,不过是用二进制格式。 [编辑]
未知类型的处理[编辑]
当静态类型和动态类型不同时(如果你有一个 object 类型的字段,但其中有一个 Person-object),似乎有两种哲学。基本上动态类型必须以某种方式存储在文件中。
对不同的动态类型使用不同的 XML 标记。但是由于要用于特定类的 XML 标记可能不等于类名,因此只有在反序列化器事先知道所有可能的类型(以便他可以扫描它们的属性)时,才可能走这条路。
在序列化期间存储 CLR 类型(类名、程序集名称和版本)。在反序列化期间使用此信息来实例化正确的类。在反序列化之前必须不知道这些类型。
第二个更易于使用,但生成的文件将依赖于 CLR(并且对代码修改不太敏感)。这可能就是XmlSerializer 和DataContractSerializer 选择第一种方式的原因。不推荐NetDataContractSerializer,因为它使用了第二种方法(顺便说一下,BinarySerializer 也是如此)。
有什么想法吗?
【问题讨论】:
-
XmlSerializer 不会失败最后一个条件。只需在构造函数中传递额外的类型。如果你有一个插件架构,只需维护一个反映的具体类型的列表。
标签: c# .net serialization xml-serialization