带有派生类型的Protobuf-net StackOverflow异常

时间:2015-04-02 23:35:36

标签: protocol-buffers protobuf-net

我正在尝试使用protobuf-net在单个频道上发送混合消息类型。我从各种来源汇总了以下示例,并在第一次反序列化时抛出了StackOverflow异常。

我是以正确的方式来做这件事的吗?

FWIW所创建文件的十六进制内容为“A2 06 02 08 02 08 01 AA 06 02 08 04 08 03”

谢谢,Greg

[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
[ProtoInclude(100, typeof(Derived1))]
[ProtoInclude(101, typeof(Derived2))]
public class Base { public int Old; }

[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public class Derived1 : Base { public int New1; }
[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public class Derived2 : Base { public int New2; }  

class Program
{
    static void Main(string[] args)
    {

        Base b1 = new Derived1() { Old = 1, New1 = 2 };
        Base b2 = new Derived2() { Old = 3, New2 = 4 };

        using (var fs = File.Create(@"C:\test.bin"))
        {
            Serializer.Serialize(fs, b1);
            Serializer.Serialize(fs, b2);
        }

        Base msg3, msg4;
        using (var fs = File.OpenRead(@"C:\test.bin"))
        {
            msg3 = Serializer.Deserialize<Base>(fs);  
            msg4 = Serializer.Deserialize<Base>(fs);
        }

        Console.WriteLine(((Derived1)msg3).New1);
        Console.WriteLine(((Derived2)msg4).New2);
        Console.ReadLine();
    }
}

2 个答案:

答案 0 :(得分:2)

我希望这里的问题是框架; protobuf(格式,而不是库)是由谷歌设计为可附加的,其中追加=== merge。如果序列化消息A,则立即序列化消息B,然后反序列化整个批次:您获得一个消息,而不是两个消息。这显然有很多可能导致意外结果,错误解释数据和错误。

然后,诀窍是对消息进行框架化,以便您可以单独处理它们。幸运的是,protobuf-net为此提供了SerializeWithLengthPrefixDeserializeWithLengthPrefix方法。在序列化期间,这会在每条消息前面添加一个标记,以指示后面的数据长度。在反序列化期间,首先读取长度前缀,允许为每条消息使用正确数量的数据。

支持多种布局和样式的长度前缀;最重要的是它们在序列化和反序列化步骤之间匹配。如果您希望数据是“纯protobuf”(即可在另一个平台上的外部消息上解析为repeated字段),那么“base-128,field 1”是一个不错的选择。

这很好用:

using (var fs = File.Create(@"test.bin"))
{
    Serializer.SerializeWithLengthPrefix(fs, b1, PrefixStyle.Base128, 1);
    Serializer.SerializeWithLengthPrefix(fs, b2, PrefixStyle.Base128, 1);
}

Base msg3, msg4;
using (var fs = File.OpenRead(@"test.bin"))
{
    msg3 = Serializer.DeserializeWithLengthPrefix<Base>(fs, PrefixStyle.Base128, 1);
    msg4 = Serializer.DeserializeWithLengthPrefix<Base>(fs, PrefixStyle.Base128, 1);
}

答案 1 :(得分:0)

我在反序列化时遇到了同样的问题,发布版本v2.1.0-alpha-1解决了这个问题。

https://docs.shopify.com/themes/development/getting-started/using-ajax-api#get-cart

此致

PLUC