Reputation: 213
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?
This is my class :
class Person
{
[ProtoMember(1)]
public int Id { get; set; }
[ProtoMember(2)]
public string Name { get; set; }
}
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);
After i create my FileDescriptor with this following command line :
protoc.exe person.proto --descriptor_set_out=person.pb
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
}
At first, I wanted to create a Dictionary of string, object instead of Person but it's impossible to serialize it.
Upvotes: 2
Views: 1604
Reputation: 1062855
I'm answering this specifically from the perspective of protobuf-net (tags); if you use the Google C# API, things will be different.
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)
.
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
.
Upvotes: 2