Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decode custom option values when classes are generated with protobuf-net

I'm using protogbuf-gen to convert proto files in C# clases. I want to convert some option from the proto file into some attribute on my classes. So I have a proto file with optionslike this:

syntax = "proto3";

import "google/protobuf/timestamp.proto";
import "google/protobuf/descriptor.proto";

enum LogOrder {
    NONE = 0;
    FIRST = 1;
    SECOND = 2;
    THIRD = 3;
}

extend google.protobuf.FieldOptions {
    LogOrder shouldBeLogged = 50001;
}

message Person {
    string  id = 1 [(shouldBeLogged)=FIRST];
    int32 business_id = 2 [(shouldBeLogged)=SECOND,deprecated=true];
...

To try doing that I had to write my own subclass of CSharpCodeGenerator wherein I could decorate the fields with an attribute in an WriteField overloaded, .

public class ServiceCodeGenerator : CSharpCodeGenerator
{
    protected override void WriteField(GeneratorContext ctx, FieldDescriptorProto obj, ref object state, OneOfStub[] oneOfs)
    {
        var bytes = obj.Options?.ExtensionData;
        // if extension data == shouldBeLogged then write somee attribute with a value

        base.WriteField(ctx, obj, ref state, oneOfs);
    }
...

But, the only thing I can get is a bytes' array which hold something like [136, 181, 24, 1] where the last byte "1" seems to be the value of "shouldBeLogged".

How can I convert those byte to something developer friendly, or otherwise access the option and its value?

like image 300
Serge Jacquemin Avatar asked May 07 '26 23:05

Serge Jacquemin


1 Answers

If you run your existing .proto through protogen, you should get, among the generated code:

public static class Extensions
{
    public static LogOrder GetshouldBeLogged(this global::Google.Protobuf.Reflection.FieldOptions obj)
        => obj == null ? default : global::ProtoBuf.Extensible.GetValue<LogOrder>(obj, 50001);

    public static void SetshouldBeLogged(this global::Google.Protobuf.Reflection.FieldOptions obj, LogOrder value)
        => global::ProtoBuf.Extensible.AppendValue<LogOrder>(obj, 50001, value);

}

This means you can use:

var shouldBeLogged = obj.Options.GetshouldBeLogged();
like image 199
Marc Gravell Avatar answered May 11 '26 16:05

Marc Gravell