dongzaliang4492 2015-08-12 01:32
浏览 497

跨平台的protobuffers,使用Protobuf-net和继承进行反序列化

Forgive, in advance, any ignorance regarding protobuffers or Go, as both of these technologies are relatively new to me.

We've been using protobuffers and protobuf-net in production for a little while. We use Redis as a message queue between systems, and everything that reads or writes to Redis uses the exact same models (a shared library) and protobuf-net to serialize and deserialize. Now, however, we want to push things into Redis from a system written in Go. My problem is that the Go-written protobuffer data is not able to be deserialized in my .NET application with protobuf-net

See the following small example for my problem.

I am using protoc version 2.6.1 for the Golang approach and protobuf-net version 2.0.0.668 for .NET

[ProtoContract]
[ProtoInclude(3, typeof(SomeDerivedClass))]
public abstract class BaseClass
{
    [ProtoMember(1)]
    public Int32 Foo { get; set; }
}

[ProtoContract]
public class SomeDerivedClass : BaseClass
{

    [ProtoMember(2)]
    public String Bar { get; set; }
}

Using Serializer.GetProto<SomeDerivedClass>(); yields the following .proto file:

message BaseClass {
   optional int32 Foo = 1 [default = 0];
   // the following represent sub-types; at most 1 should have a value
   optional SomeDerivedClass SomeDerivedClass = 3;
}
message SomeDerivedClass {
   optional string Bar = 2;
}

Which, using protogen, yielded the following .go file: https://gist.github.com/cjqed/408dd9fd11e935239f36

Then,

derived := &SomeDerivedClass{
    Bar: proto.String("h"),
}
baseClass := &BaseClass{
    SomeDerivedClass: derived,
    Foo: proto.Int32(13),
} 
data, err := proto.Marshal(baseClass)
if err != nil {
    panic(err)
}

When deserialized with protobuf-net, results in

Result: ProtoException, No parameterless constructor found for BaseClass

...Unless I make BaseClass non-abstract. Which, although possible, is not really a good solution.

Finally, I made the exact same object in protobuf-net and in Go (both on the same machine, mind you), and these are the bytes for each:

(Code in protobuf-net to serialize)

var obj = new SomeDerivedClass
{
    Bar = "h",
    Foo = 13
};
byte[] data;

using (var memoryStream = new MemoryStream())
{
    Serializer.Serialize(memoryStream, obj);
    data = memoryStream.ToArray();
}

Protobuf-net:
26, 3, 18, 1, 104, 8, 13

With github.com/golang/protobuf/proto:
8, 13, 26, 3, 18, 1, 104

Note the last two bytes in protobuf-net are the first two in golang.

So, am I doing something wrong, or is there a bug in one of the two protobuffer libraries? Or maybe in the go protogen?

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 安卓adb backup备份应用数据失败
    • ¥15 eclipse运行项目时遇到的问题
    • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
    • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
    • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
    • ¥50 成都蓉城足球俱乐部小程序抢票
    • ¥15 yolov7训练自己的数据集
    • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
    • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
    • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)