我遇到过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的问题吗?
非常感谢任何帮助。
干杯
亚历
答案 0 :(得分:1)
在实现作为合同的接口时,有一些未完成的工作需要完成以改进顶级对象的处理。基本上,目前它只处理根对象的非接口部分,但处理属性/子对象等的接口。
你看到的例外是略微奇怪 - 由于ifoo
属性,我希望它及时知道subfoo
,但这里的根本问题可以通过添加:
Serializer.PrepareSerializer<ifoo>();
在序列化代码之前(理想情况是很早的某个地方;你只需要调用一次)。
但是,我还应该注意到你实际上在这里进行了双序列化:序列化ifoo subfoo
属性时,它将从接口接口({{1具体类型(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; }
}
包装器,但我可能需要添加一些开关来启用/禁用修复,以用于传统支持。 / p>