本文介绍了有没有办法用 DescriptorProto 反序列化未知对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to find a way to deserialize an unknown object with a DescriptorProto. When I serialize a Person, it's not a problem because I know its type. But when I deserialize, I don't know the type of object I receive so how with DescriptorProto, which define the structure of the proto, I can create an object like an ExpandObject?

这是我的课:

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

我用一些值创建了一个对象 Person,将它序列化并创建我的 .proto :

I create an object Person with some values, serialize it and create my .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 之后:

After i create my FileDescriptor with this following command line :

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

最后,我想用 person.pb 的描述反序列化我的 person.bin,如下所示:

Finally i want to deserialize my person.bin with the description of person.pb like this :

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
}

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

At first, I wanted to create a Dictionary of string, object instead of Person but it's impossible to serialize it.

推荐答案

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

I'm answering this specifically from the perspective of protobuf-net (tags); if you use the Google C# API, things will be different.

这里有一些不同的东西;然而,protobuf-net 目前没有 API 来加载特别的描述符!它确实有一个 Extensible 基类,可用于反序列化任何任意负载,以及 Extensible 上的 static 方法code> 例如 Extensible.GetValue(1).所以;这使您能够读取(或写入)任意负载.您可能需要创建一个非抽象类来使用,但 class Foo : Extensible {} 应该就足够了,然后 Serializer.Deserialize(source).

There's a couple of different things here; protobuf-net does not currently have an API to load things specifically taking a descriptor, however! It does have an Extensible base class which can be used to deserialize any arbitrary payload, along with the static methods on Extensible such as Extensible.GetValue<int>(1). So; that gives you the ability to read (or write) an arbitrary payload. You might need to create a non-abstract class to play with, but class Foo : Extensible {} should suffice, then Serializer.Deserialize<Foo>(source).

所以;第二部分是如何解析描述符.为此,请参阅 protobuf-net.Reflection包.这包括您期望的常用描述符类型,包括 FileDescriptorSet,因此:您可以使用 protobuf-net 的常规 Serializer.Deserialize(source) 来获取描述符-设置,您可以从其中以通常的方式拆分模型并发现属性,以与 Extensible 一起使用.

So; the second part is how to parse a descriptor. For that, see the protobuf-net.Reflection package. This includes the usual descriptor types you would expect, including FileDescriptorSet, so: you can use protobuf-net's regular Serializer.Deserialize<FileDescriptorSet>(source) to get a descriptor-set, from which you can pull apart the model in the usual way and discover the properties, to use with Extensible.

这篇关于有没有办法用 DescriptorProto 反序列化未知对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!