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

时间:2015-08-12 01:32:39

标签: c# go protocol-buffers protobuf-net

事先原谅任何关于protobuffers或Go的无知,因为这两种技术对我来说都比较新。

我们已经在生产中使用protobuffers和protobuf-net一段时间了。我们使用Redis作为系统之间的消息队列,读取或写入Redis的所有内容都使用完全相同的模型(共享库)和protobuf-net来序列化和反序列化。但是,现在我们想要用Go编写的系统将内容推送到Redis中。我的问题是,使用protobuf-net在我的.NET应用程序中无法对Go编写的protobuffer数据进行反序列化

针对我的问题,请参阅以下小例子。

我正在使用protoc版本2.6.1用于Golang方法和protobuf-net版本2.0.0.668用于.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; }
}

使用Serializer.GetProto<SomeDerivedClass>();会生成以下.proto文件:

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;
}

使用protogen,产生以下.go文件: https://gist.github.com/cjqed/408dd9fd11e935239f36

然后,

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

使用protobuf-net反序列化时,会产生

结果:ProtoException, No parameterless constructor found for BaseClass

......除非我使BaseClass非抽象。虽然可能,但这并不是一个很好的解决方案。

最后,我在protobuf-net和Go中创建了完全相同的对象(两者都在同一台机器上,请注意),这些是每个的字节:

(protobuf-net中的代码序列化)

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

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

protobuf网:
26, 3, 18, 1, 104, 8, 13

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

注意protobuf-net中的最后两个字节是golang中的前两个字节。

那么,我做错了什么,或者两个protobuffer库中有一个错误?或者也许是去生素?

0 个答案:

没有答案