Есть ли способ десериализации неизвестного объекта с DescriptorProto? - PullRequest
1 голос
/ 15 мая 2019

Я хочу найти способ десериализации неизвестного объекта с помощью 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.bin с описанием person.pb следующим образом:

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 , но его невозможно сериализовать.

1 Ответ

1 голос
/ 17 мая 2019

Я отвечаю на это конкретно с точки зрения protobuf-net (теги);если вы используете API Google C #, все будет иначе.

Здесь есть несколько разных вещей;Однако у protobuf-net нет API для загрузки вещей , в частности , с использованием дескриптора!Он имеет базовый класс Extensible, который можно использовать для десериализации любой произвольной полезной нагрузки, наряду с методами static в Extensible, такими как Extensible.GetValue<int>(1).Так;это дает вам возможность читать (или писать) произвольную полезную нагрузку.Возможно, вам придется создать неабстрактный класс для игры, но достаточно class Foo : Extensible {}, тогда Serializer.Deserialize<Foo>(source).

Итак;вторая часть - как разобрать дескриптор.Для этого см. Пакет protobuf-net.Reflection.Это включает в себя обычные типы дескрипторов, которые вы ожидаете, включая FileDescriptorSet, поэтому: вы можете использовать обычный Serializer.Deserialize<FileDescriptorSet>(source) protobuf-net, чтобы получить набор дескрипторов, из которого вы можете отделить модель обычным способом и обнаружить свойства, для использования с Extensible.

...