Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate C# from proto files and vice versa interpreting custom options

I'm using protobuf-net, and I'm trying to:

  1. Generate a C# class from a .proto file
  2. Generate a .proto file from a C# class

That's pretty easy using respectively:

  1. protogen.exe tool
  2. Serializer<T>.GetProto() method

But the thing is that I need to support protobuffer custom options and it doesn't seem to be as straightforward as I though.

Let me explain:

  1. From a proto file containing custom options applied on messages and fields, I want to generate a C# class decorated by .NET custom attributes.
  2. From a C# class decorated by custom attributes, I would like to generate a proto file where custom options are applied on messages and fields.

Basically, given:

message person {
   option (my_message_option) = true;

   optional string firstname = 1 [(my_field_option) = 42];
   optional string lastname = 2 [(my_field_option) = 12];
   optional int age = 3;
}

I want to generate:

[ProtoContract, MyMessageOption(true)]
public class Person
{
    [ProtoMember(1), MyFieldOption(42)]
    public string Firstname;

    [ProtoMember(2), MyFieldOption(12)]
    public string Firstname;

    [ProtoMember(3)]
    public string Firstname;
}

...and vice versa.

Notes :

  • The custom option definitions (my_message_option and my_field_option) can already exist in a protofile (say, my_custom_options.proto), and the custom attributes classes can also exist somewhere (MyMessageOptionAttribute and MyFieldOptionAttribute).
  • I tried to use protogen.exe and a custom xslt but protogen doesn't seem to have support for custom options.

What's the preferred way to achieve that? The solution doesn't have to rely on protobuf-net.

like image 501
Romain Verdier Avatar asked Mar 28 '11 11:03

Romain Verdier


2 Answers

I ended up by forking ProtoGen project from protobuf-csharp to make public some internal types (generators, for the most part) and to make the SourceGenerators extensible by allowing custom generator registrations.

This way, I was able to use the proto descriptor object model to write my own C# generator.

One tricky point is to register your custom options types before launching the parsing :

  1. Generate C# types corresponding to your custom options (using Protoc.exe then ProtoGen.exe)
  2. Configure ExtensionRegistry by using the generated RegisterAllExtensions methods.
  3. Start the code generation using your own C# generators. In each generator you can access to the contextual Descriptor.Options collection.
like image 197
Romain Verdier Avatar answered Oct 08 '22 15:10

Romain Verdier


There isn't a simple way to do this at the moment. The changes required would primarily be to the csharp.xslt file. There is a bug reported about this but hasn't been fixed yet.

like image 29
Marc Gravell Avatar answered Oct 08 '22 13:10

Marc Gravell