有没有办法使用DescriptorProto反序列化未知对象?

时间:2019-05-15 07:10:03

标签: c# protocol-buffers protobuf-net

我想找到一种使用DescriptorProto反序列化未知对象的方法。当我序列化 Person 时,这不是问题,因为我知道它的类型。但是,当我反序列化时,我不知道收到的对象的类型,那么如何使用DescriptorProto定义原型的结构,我可以创建一个像ExpandObject这样的对象?

这是我的课程:

    class Person
    {
        [ProtoMember(1)]
        public int Id { get; set; }
        [ProtoMember(2)]
        public string Name { get; set; }
    }

我创建一个具有某些值的对象Person,对其进行序列化并创建我的.proto:

var person = new Person
{
   Id = 12345,
   Name = "Fred"
};
using (var file = File.Create(@"C:\temp\protobuf\person.bin"))
{
   Serializer.Serialize(file, person);
   file.SetLength(file.Position);
}
string proto = Serializer.GetProto<Person>();
File.WriteAllText(@"C:\temp\protobuf\person.proto", proto);

使用以下命令行创建FileDescriptor之后:

protoc.exe person.proto --descriptor_set_out=person.pb

最后,我想使用 person.pb 的描述反序列化我的 person.bin

byte[] payload = System.IO.File.ReadAllBytes(@"C:\temp\protobuf\person.pb");
FileDescriptorSet fileDescriptorSet = FileDescriptorSet.ParseFrom(payload);
FileDescriptorProto fileDescriptorProto = fileDescriptorSet.GetFile(0);
DescriptorProto requestDescriptor = fileDescriptorProto.GetMessageType(0);

/**
             requestDescriptor : 

            {name: "Person"
                field {
                  name: "Id"
                  number: 1
                  label: LABEL_OPTIONAL
                  type: TYPE_INT32
                  default_value: "0"
                }
                field {
                  name: "Name"
                  number: 2
                  label: LABEL_OPTIONAL
                  type: TYPE_STRING
                }
             }

             **/

object youhou;
using (var file = File.OpenRead(@"C:\temp\protobuf\person.bin"))
{
    //youhou = Serializer.Deserialize<Person>(file);
    // I don't know **Person** so i can't do this
}

起初,我想创建一个字符串,对象的字典,而不是,但是无法序列化它。

1 个答案:

答案 0 :(得分:1)

我要从protobuf-net(标签)的角度具体地回答这个问题;如果您使用Google C#API,情况将会有所不同。

这里有两件事。 protobuf-net当前没有使用描述符来特定地加载 的API!它确实有一个Extensible基类,可用于反序列化任何有效载荷,以及static上的Extensible方法,例如Extensible.GetValue<int>(1) 。所以;使您能够读取(或写入)任意有效负载。您可能需要创建一个非抽象类来玩,但是class Foo : Extensible {}就足够了,然后Serializer.Deserialize<Foo>(source)就可以了。

所以;第二部分是如何解析描述符。为此,请参见protobuf-net.Reflection软件包。这包括您期望的常规描述符类型,包括FileDescriptorSet,因此:您可以使用protobuf-net的常规Serializer.Deserialize<FileDescriptorSet>(source)来获取描述符集,然后可以按照常规方式将模型拆开并发现要与Extensible一起使用的属性。