Reading a protobuf3 custom option from C#

You can now access custom options in C#. First, define the custom option in your .proto:

import "google/protobuf/descriptor.proto";
extend google.protobuf.FieldOptions {
  string objectReferenceType = 1000; //Custom options are 1000 and up.
}

Next, apply the custom option to something. Here I attached it to a field:

message Item
{
  string name = 1;
  int32 id = 2;
  string email = 3;
  ObjectReference prefab = 4 [(objectReferenceType) = "UnityEngine.GameObject"];
}

Then you need to lookup the custom option field number. There's no nice way to do this, so just look up the extension from FileDescriptor of the file where you defined the custom option extension. You will have a C# generated class called protoFileNameReflection. From that, you can find the extension then the field number. Here's an example assuming the proto is called "Item.proto" so the generated class is called ItemReflection:

foreach (FieldDescriptor extensionFieldDescriptor in ItemReflection.Descriptor.Extensions.UnorderedExtensions)
    {   
        if (extensionFieldDescriptor.ExtendeeType.FullName == "google.protobuf.FieldOptions")
        {
            objectReferenceTypeFieldNumber = extensionFieldDescriptor.FieldNumber;
            break;
        }
    }

Then access the custom option in code using protobuf reflection:

FieldDescriptor fieldDescriptor = prefabFieldDescriptor;
CustomOptions customOptions = fieldDescriptor.CustomOptions;
if (customOptions.TryGetString(objectReferenceTypeFieldNumber, out string objectReferenceTypeText))
{
   Console.Log(objectReferenceTypeText); //logs: "UnityEngine.GameObject"
}

Looks like the feature hasn't been implemented yet: https://github.com/google/protobuf/issues/1603

It also looks like it's only a matter of time and they're open to pull requests. So depending on how soon you need it, you could be the one doing the implementation :)