C# 二进制对象图序列化

C# 二进制对象图序列化,c#,.net,serialization,protocol-buffers,binaryformatter,C#,.net,Serialization,Protocol Buffers,Binaryformatter,我正在寻找关于.net应用程序序列化的建议。该应用程序是桌面/厚客户端应用程序,序列化表示持久化文档格式。序列化程序的要求如下所示 必须允许序列化字段,而不仅仅是公共属性 不能要求无参数构造函数 必须处理一般对象图,即不仅是DAG,而且是共享/双向引用 必须使用框架类(例如序列化字典) 目前,我们使用BinaryFormatter,它可以很好地处理上述所有问题,但是大小/性能和版本公差是一个问题。我们使用[OnDeserialized/ing]属性来提供兼容性,但它不允许在不复杂使用代理等情

我正在寻找关于.net应用程序序列化的建议。该应用程序是桌面/厚客户端应用程序,序列化表示持久化文档格式。序列化程序的要求如下所示

  • 必须允许序列化字段,而不仅仅是公共属性
  • 不能要求无参数构造函数
  • 必须处理一般对象图,即不仅是DAG,而且是共享/双向引用
  • 必须使用框架类(例如序列化字典)
目前,我们使用BinaryFormatter,它可以很好地处理上述所有问题,但是大小/性能和版本公差是一个问题。我们使用[OnDeserialized/ing]属性来提供兼容性,但它不允许在不复杂使用代理等情况下进行大规模重构(比如名称空间更改)

一个理想的解决方案是替换BinaryFormatter,它可以与我们现有的[NonSerialized]注释一起工作,但性能更好,并且生成更小、更易于维护的格式

我已经研究了不同的protobuf实现,尽管现在似乎可以序列化一般对象图/枚举/结构,但是序列化具有许多框架集合类型等的复杂图似乎并不简单,即使我们可以让它与字段而不是属性一起工作,我理解这仍然意味着必须向所有类添加无参数构造函数和protobuf注释(该域大约有1000个类)

因此,问题是:

  • 有没有提供文档化格式的“替代”二进制格式化程序性能更好
  • 协议缓冲区是否适用于持久化大型通用对象图(包括框架类型)
试试看,它不是一个真正的序列化程序,但据我所知,它满足您的需求(复杂类型、深度图、继承?、字典等),您不必对对象进行任何更改,而且API非常易于使用

它支持模式版本控制/合并。

协议缓冲区作为一种格式,没有对对象图的正式支持,但protobuf net确实提供了这一功能,并满足您的其他要求。依次考虑以下要点:

  • 必须允许序列化字段,而不仅仅是公共属性
当然;protobuf net可以为公共和非公共字段执行此操作;在运行时或通过属性告诉它有关字段的信息

  • 不能要求无参数构造函数
这在“v2”中可用——同样,您可以告诉它在运行时跳过构造函数,或者通过属性(
SkipConstructor=true
在合同上)

  • 必须处理一般对象图,即不仅是DAG,而且是共享/双向引用
当然;在成员上标记
AsReference=true

  • 必须使用框架类(例如序列化字典)
标准的列表和字典工作良好;但是,我有一个未完成的更改请求,需要在词典中支持
AsReference
。也就是说,
Dictionary
目前不会运行
Foo
的图形代码,但是如果它给您带来了很大的痛苦,我可能会找一些时间来看看它

  • 我们使用[OnDeserialized/ing]属性来提供兼容性
完全支持序列化回调

  • 但它不允许在不复杂使用代理等的情况下进行大规模重构(比如名称空间更改)
protobuf net对名称空间等一点也不感兴趣(除非您使用的是
DynamicType
选项)

  • 这仍然意味着必须向所有类添加无参数构造函数和protobuf注释

不一定;如果您可以保证不会更改字段名称,您可以要求它在内部推断字段编号,最终在“v2”中,所有内容都可以在运行时指定,因此您通常可以编写一个小的配置循环,在应用程序启动时运行,并使用反射来配置系统。这样,您就根本不需要更改现有代码。

感谢您快速而详细的回复。我想看看最近在《v2》中发生了什么。我可以实现这个策略吗:假设一个未注释的类有隐式protobuf注释,这样所有可序列化的字段都包括在内,比如按字母顺序。所有引用字段都作为引用。一旦我更改了一个类,我可以添加显式属性吗?另外,ISerializable/IObjectReference/IDeserializationCallback是否有效(比如我有?@Anders-
ISerializable
;没有。
IDeserializationCallback
/
IObjectReference
)-我需要检查。你是“更改类”吗-如果我正确理解了这个问题,那么是的-您可以在以后添加属性,以保持与早期定义的兼容性。Marc,我已通过反映我的域类型并将所有字段添加为引用成功创建了一个模型。我在框架类中遇到的一个问题是AsReference(也许这就是你在回答中所说的):如果我有var shapes=new List{circle1,circle1,rect1};也就是说,同一个对象出现两次,我希望通过序列化来保留该图。我能说服作者跳过集合的序列序列化,而只是序列化字段(例如,列表的内部数组)吗,并对所有引用字段(包括框架类)保持引用意识?@Anders在集合中跟踪引用的问题只是“该死的,我需要找几分钟来调整它”(并找到一种方法来指导它这么做)。如果这是一个障碍,我可能可以在今晚(大约8/9小时的时间)看到它.我不想逼你去贬低你的创意孩子马克.你可能会注意到,我正试着做一个代替你的人