【问题标题】:Decode custom option values when classes are generated with protobuf-net使用 protobuf-net 生成类时解码自定义选项值
【发布时间】:2018-09-06 21:47:44
【问题描述】:

我正在使用 protogbuf-gen 来转换 C# 类中的 proto 文件。 我想将 proto 文件中的一些 optionconvert 转换为我的类的一些 attribute。 所以我有一个带有如下选项的原型文件:

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];
...

要尝试这样做,我必须编写自己的 CSharpCodeGenerator 子类,在其中我可以使用重载的 WriteField 中的属性来装饰字段。

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);
    }
...

但是,我唯一能得到的是一个字节数组,它包含类似 [136, 181, 24, 1] 的东西,其中最后一个字节“1”似乎是“shouldBeLogged”的值。

如何将这些字节转换为对开发人员友好的内容,或者以其他方式访问选项及其值?

【问题讨论】:

    标签: protocol-buffers protobuf-net


    【解决方案1】:

    如果你通过 protogen 运行现有的 .proto,你应该在生成的代码中得到:

    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);
    
    }
    

    这意味着您可以使用:

    var shouldBeLogged = obj.Options.GetshouldBeLogged();
    

    【讨论】:

    • 所以,我必须生成一次类。将我的 WriteField 重载更改为使用 GetshouldBeLogged 方法。然后再次生成类?
    • @SergeJacquemin 如果你不想这样做,直接使用global::ProtoBuf.Extensible.GetValue&lt;LogOrder&gt;(obj, 50001); - 如果枚举不可用,则使用&lt;int&gt;。我假设生成的类型与使用它的地方是分开的
    • 感谢 Marc,我没有尝试过使用 。但最后,我不得不硬编码 50001,所以我最终自己从 obj.Options?.ExtensionData 解码字节数组(仅支持 Varint)。
    猜你喜欢
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多