protobuf-net 并使用接口序列化链表
Posted
技术标签:
【中文标题】protobuf-net 并使用接口序列化链表【英文标题】:protobuf-net and serializing a linked list using interfaces 【发布时间】:2012-09-27 14:00:20 【问题描述】:我遇到了 protobuf-net 的问题,并将其缩小到这个最简单的情况。 我想要一个链表类型结构,其中一个类具有相同类型的属性。当我序列化它时,它工作得很好。但是,如果类型是接口而不是类,我会收到以下错误: 一旦为 ConsoleApplication1.foo (ConsoleApplication1.ifoo) 生成了序列化程序,就无法更改类型
这是我必须生成此错误的代码:
class Program
static void Main(string[] args)
var toSerialize = new foo();
toSerialize.data = "foo1";
var subf = new foo();
subf.data = "foo2";
toSerialize.subfoo = subf;
using (var pbfsc = new FileStream("testfile.proto", FileMode.Create))
using (var cs = new GZipStream(pbfsc, CompressionMode.Compress))
ProtoBuf.Serializer.Serialize(cs, toSerialize);
pbfsc.Close();
[ProtoContract, ProtoInclude(2000, typeof(foo))]
public interface ifoo
[ProtoMember(1)]
string data get; set;
[ProtoMember(2)]
ifoo subfoo get; set;
[ProtoContract]
public class foo : ifoo
[ProtoMember(1)]
public string data get; set;
[ProtoMember(2)]
public ifoo subfoo get; set;
我已尽我所能阅读了有关该主题的所有内容,但我看不出我做错了什么。我尝试将我的对象放在一个包装类中,因为它看起来类似于接口列表的问题(代码未显示),但这仍然没有帮助。
如果我将 subfoo 更改为 foo 类型,那么它可以正常工作,但在我更复杂的现实世界问题中,我宁愿坚持使用界面。我在这里做错了什么还是 protobuf-net 有问题?
非常感谢任何帮助。
干杯
亚历克斯
【问题讨论】:
【参考方案1】:当顶层对象实现一个作为契约的接口时,需要完成一些出色的工作来改进对它的处理。基本上,目前它只处理根对象的非接口部分,但处理属性/子对象等的接口。
您看到的异常有点奇怪 - 由于subfoo
属性,我希望它及时了解ifoo
,但这里的基本问题可以通过以下方式避免添加:
Serializer.PrepareSerializer<ifoo>();
在序列化代码之前(最好是在很早的地方;您只需要调用一次)。
但是,我还应该注意,您实际上在这里进行了双重序列化:当序列化 ifoo subfoo
属性时,它将序列化来自接口 both 的修饰成员 (ifoo
) 和具体类型(foo
)。这些实际上是相同的值,所以这里有一些冗余。
我会说:从具体类型中去掉成员级别的属性,但是根对象故障使这有点问题。解决两个问题(不再需要PrepareSerializer
)的另一个修复是:
using ProtoBuf;
using System;
class Program
static void Main(string[] args)
var root = new foo();
root.data = "foo1";
var subf = new foo();
subf.data = "foo2";
root.subfoo = subf;
var toSerialize = new FooRoot root = root ;
// this does the same as your file-code, but runs
// both serialize and deserialize - basicaly, it is
// a lazy way of checking it end-to-end
var clone = Serializer.DeepClone(toSerialize).root;
Console.WriteLine(clone.data); // "foo1"
Console.WriteLine(clone.subfoo.data); // "foo2"
[ProtoContract]
public class FooRoot
[ProtoMember(1)]
public ifoo root get; set;
[ProtoContract, ProtoInclude(2000, typeof(foo))]
public interface ifoo
[ProtoMember(1)]
string data get; set;
[ProtoMember(2)]
ifoo subfoo get; set;
[ProtoContract]
public class foo : ifoo
public string data get; set;
public ifoo subfoo get; set;
解决根对象/接口支持故障后,将不再需要 FooRoot
包装器,但我可能需要添加一些开关来启用/禁用修复,以获得旧版支持。
【讨论】:
以上是关于protobuf-net 并使用接口序列化链表的主要内容,如果未能解决你的问题,请参考以下文章
我可以反序列化为 protobuf-net 中接口的只读属性吗?