二进制对象图序列化
我正在寻找有关 .net 应用程序中序列化的建议。该应用程序是桌面/胖客户端应用程序,序列化代表持久的文档格式。序列化器的要求是
- 必须允许序列化字段,而不仅仅是公共属性。
- 不得要求无参数构造函数。
- 必须处理一般对象图,即不仅是 DAG,还有共享/双向引用。
- 必须使用框架类(例如序列化字典)。
目前我们使用 BinaryFormatter 可以很好地处理上述所有问题,但大小/性能和版本容差是一个问题。我们使用 [OnDeserialized/ing] 属性来提供兼容性,但它不允许在不复杂使用代理等的情况下进行大型重构(例如命名空间更改)。
理想的解决方案是 BinaryFormatter 的直接替代品,它与我们现有的 [NonSerialized] 注释等一起使用,但性能更好,并生成更小且更易于维护的格式。
我已经研究了不同的 protobuf 实现,尽管现在似乎可以序列化通用对象图/枚举/结构,但序列化具有大量框架集合类型等的复杂图似乎并不简单。此外,即使我们可以让它使用字段而不是属性我理解这仍然意味着必须向所有类添加无参数构造函数和 protobuf 注释(域大约有 1000 个类)。
所以问题是:
- 是否有任何“替代”二进制格式化程序,可以提供良好记录的格式,性能更好?
- 协议缓冲区是否适合持久保存大型通用对象图(包括框架类型)?
I'm looking for advice on serialization in a .net app. The app is a desktop/thick client app and the serialization represents the persisted document format. The requirements for the serializer is
- Must allow serializing fields, not public properties only.
- Must not require parameterless constructors.
- Must handle general object graphs, i.e. not only DAG but shared/bidirectional references.
- Must work with framework classes (e.g. Serialize Dictionaries).
Currently we use the BinaryFormatter which handles all of the above quite well, but size/performance and version tolerance is an issue. We use the [OnDeserialized/ing] attributes to provide compatibility, but it does not allow for large refactorings (say a namespace change) without complex use of surrogates and so on.
An ideal solution would be a drop-in replacement for BinaryFormatter that works with our existing [NonSerialized] annotations etc., but performs better, and produces a format that is smaller and easier to maintain.
I have looked at the different protobuf implementations, and even though it seems possible to serialize general object graphs/enums/structs these days, it does not appear trivial to serialize a complex graph with a lot of framework collection types etc. Also, even if we could make it work with fields rather than properties I understand it would still mean having to add parameterless constructors and protobuf annotations to all classes (The domain is around 1000 classes).
So the questions:
- Are there any "alternative" Binary formatters, that provide a well documented format, perform better?
- Are protocol buffers ever suitable for persisting large general object graphs including framework types?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Protocol buffers 作为一种格式没有对对象图的官方支持,但 protobuf-net 确实提供了这一点,并满足您的其他要求。依次取点:
当然; protobuf-net 可以为公共和非公共领域做到这一点;在运行时或通过属性告诉它有关字段的信息
这在“v2”中可用 - 同样,您可以告诉它在运行时或通过属性跳过构造函数(合约上的
SkipConstructor=true
)当然;在成员上标记
AsReference=true
标准列表和字典工作正常; 但是,我有一个未完成的更改请求,以支持内部字典的
AsReference
。意思是,Dictionary
当前不会运行Foo
的图形代码,但我可能可以找一些时间来查看如果它给您带来很大的痛苦,完全支持序列化回调
命名空间等对 protobuf-net 来说一点也不有趣(除非您使用 DynamicType 选项),
不一定;如果您可以保证不会更改字段名称,您可以要求它在内部推断字段编号 - 最终在“v2”中一切都可以在运行时,因此您通常可以编写一个在应用程序启动时运行的小型配置循环,并使用反射来配置系统。那么您根本不需要更改现有代码。。
Protocol buffers as a format has no official support for object graphs, but protobuf-net does provide this, and meets your other requirements. To take the points in turn:
Sure; protobuf-net can do that for both public and non-public fields; tell it about the fields at either runtime or via attributes
That is available in "v2" - again, you can tell it to skip the constructor at runtime or via attributes (
SkipConstructor=true
on the contract)Sure; mark
AsReference=true
on a memberStandard lists and dictionaries work fine; however, I have an outstanding change request to support
AsReference
inside a dictionary. Meaning,Dictionary<string, Foo>
won't currently run the graph code forFoo
, but I can probably find a few moments to look at this if it is causing you significant painSerialization callbacks are fully supported
Namespaces etc are not at all interesting to protobuf-net (unless you are using the
DynamicType
options)Not necessarily; if you can guarantee that you won't change the field names, you can ask it to infer the field numbers internally - and ultimately in "v2" everything can be specified at runtime, so you can often write a small configuration loop that runs at app-startup and uses reflection to configure the system. Then you do not need to change your existing code at all.
尝试 db4o,它并不是真正的序列化器,但据我所知它满足您的要求(复杂类型,深度图形、继承?、字典等),您不必更改对象上的任何内容,并且 API 非常易于使用。
它支持模式版本控制/合并。
Try db4o, it's not realy a serializer but as far as I can tell it meets your requirements (complex types, deep graph, inheritance?, dictionaries etc), you don't have to change anything on your objects, and the API is extremely easy to use.
It supports schema versioning/merging.