nj_bubbles
nj_bubbles

Reputation: 78

Is it possible to generate C# files using protobuf-net for proto2 files with extension of 'FieldOptions'?

I have a proto file with proto2 syntax. I am trying to auto-generate C# file using the protogen. Although I can generate the file without any errors, I get an error while building the project (the C# file is part of a .Net 5 project in Visual Studio). The error looks like :

error CS0400: The type or namespace name 'Google' could not be found in the global namespace (are you missing an assembly reference?)

I have added the 'descriptor.proto' in the correct path but it does not seem to make any difference in how protogen auto-generates the C# file.

myproto.proto

syntax = "proto2";

import "google/protobuf/descriptor.proto";

package test;

extend google.protobuf.FieldOptions {
  optional string sampleValue = 50004;
}

message TestMessage {
  required string id = 1;
  optional float value = 2;
  optional string sample_val = 3;
}

myproto.cs

// <auto-generated>
//   This file was generated by a tool; you should avoid making direct changes.
//   Consider using 'partial classes' to extend these types
//   Input: myproto.proto
// </auto-generated>

#region Designer generated code
#pragma warning disable CS0612, CS0618, CS1591, CS3021, IDE0079, IDE1006, RCS1036, RCS1057, RCS1085, RCS1192
namespace Test
{

    [global::ProtoBuf.ProtoContract()]
    public partial class TestMessage : global::ProtoBuf.IExtensible
    {
        private global::ProtoBuf.IExtension __pbn__extensionData;
        global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
            => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing);

        [global::ProtoBuf.ProtoMember(1, Name = @"id", IsRequired = true)]
        public string Id { get; set; }

        [global::ProtoBuf.ProtoMember(2, Name = @"value")]
        public float Value
        {
            get => __pbn__Value.GetValueOrDefault();
            set => __pbn__Value = value;
        }
        public bool ShouldSerializeValue() => __pbn__Value != null;
        public void ResetValue() => __pbn__Value = null;
        private float? __pbn__Value;

        [global::ProtoBuf.ProtoMember(3, Name = @"sample_val")]
        [global::System.ComponentModel.DefaultValue("")]
        public string SampleVal
        {
            get => __pbn__SampleVal ?? "";
            set => __pbn__SampleVal = value;
        }
        public bool ShouldSerializeSampleVal() => __pbn__SampleVal != null;
        public void ResetSampleVal() => __pbn__SampleVal = null;
        private string __pbn__SampleVal;

    }

    public static partial class Extensions
    {
        public static string GetsampleValue(this global::Google.Protobuf.Reflection.FieldOptions obj)
            => obj == null ? default : global::ProtoBuf.Extensible.GetValue<string>(obj, 50004);

        public static void SetsampleValue(this global::Google.Protobuf.Reflection.FieldOptions obj, string value)
            => global::ProtoBuf.Extensible.AppendValue<string>(obj, 50004, value);

    }
}

#pragma warning restore CS0612, CS0618, CS1591, CS3021, IDE0079, IDE1006, RCS1036, RCS1057, RCS1085, RCS1192
#endregion

The error occurs in the static class Extensions for both methods in the generated 'myproto.cs'. Isn't it possible to use only the protobuf-net package without any additional Google packages? If not then which package do I have to add as additional dependency? I might be missing something trivial but I can't seem to understand as of now.

Upvotes: 2

Views: 1247

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1062780

No Google reference is needed here; you have extended FieldOptions, which is the descriptor metadata type that relates to fields. protobuf-net has an implementation of that in the protobuf-net.Reflection package, in exactly where this could be expected: Google.Protobuf.Reflection.FieldOptions.

However! I doubt that this is going to do what you expect. In this scenario, you have defined a "custom option". Custom options aren't related to runtime instance data - they are part of the .proto DSL, and are usually used to influence code generation; in your case, it would be something like:

  optional string sample_val = 3 [sampleValue= "ExtensionTypeName"];

(or something like that)

The point here is that the value ("ExtensionTypeName") only applies when talking about the schema field, which is why it is dangling off of FieldOptions (which represents an instance of a schema field definition). It has nothing whatsoever to do with your TestMessage usage at runtime. Further: protobuf-net does not currently package custom options into the generated C# (it could do, presumably as a base-64 chunk in an attribute, or similar - it just doesn't currently).

So: taking this back a step: what does your extension sampleValue mean to you, and to what instances do you see it relating?

Upvotes: 3

Related Questions