c# - 具有 ProtoBuf.Meta 接口(interface)的模仿 ProtoEnumAttribute

标签 c# protobuf-net

protobuf-net ,您可以使用 ProtoEnumAttribute 覆盖枚举的有线格式,如下所示:

[ProtoContract]
enum MyEnum
{
  [ProtoEnum(Value=1)]
  Default,
  [ProtoEnum(Value=10)]
  Foo
}

使用这些属性,Default 通常会序列化为 0Foo1,现在它们将序列化分别为 110

我想做的是使用 ProtoBuf.Meta 中的接口(interface)来模仿这种行为,所以我不必注释枚举(因为我通常不在我的项目中控制它们)。

通过挖掘 protobuf-net 的源代码,我成功地实现了以下(稍微简化)工作:

var model = RuntimeTypeModel.Create();
var meta = model.Add(enumType, applyDefaultBehaviour: true);

var fields = meta.GetFields();

// Oh god why
var fieldNumber = 
      typeof(ValueMember).GetField(
        "fieldNumber", 
        System.Reflection.BindingFlags.Instance | 
        System.Reflection.BindingFlags.NonPublic
      );

List<string> ordered = GetDesiredEnumOrder(enumType);
int equiv = 0;
foreach (var val in ordered)
{
    var field = fields.Single(f => f.Name == val);
    fieldNumber.SetValue(field, equiv);
    equiv++;
}

但是,我无法依靠反射到私有(private)(只读!)字段来传递它,这只是自找麻烦。

那么,是否有一种受支持的方法可以在运行时在 protobuf-net 中覆盖枚举线值?

最佳答案

我不在电脑前检查这一点,所以如果我胡言乱语,你必须纠正我,但它应该是这样的(在应用程序的早期):

RuntimeTypeModel.Default.Add(typeof(MyEnum), false)
    .Add(1, "Default").Add(10, "Foo");

第一行告诉它向模型添加一个新的Type(false)应用任何常用规则;第二行向该类型的表示添加 2 个成员以及所需的值。

如果这不起作用(我会在今天晚些时候尝试检查),请告诉我,我会让它起作用(或提供等效的 API)。可能只是在没有属性的情况下工作时,这种情况根本没有出现让我验证它。

关于c# - 具有 ProtoBuf.Meta 接口(interface)的模仿 ProtoEnumAttribute,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13783894/

相关文章:

protocol-buffers - 如何从 protobuf-net 中获得最大性能

c# - 有没有办法在设置类的任何属性时调用方法?

C# int 到标志枚举

c# - 如何限制类型属性的 NDepend 方法查询

c# - protobuf-net:无法反序列化 ReadOnlyCollection

c# - protobuf-net 没有反序列化 DateTime.Kind 正确

c# - 如何显示作为 int[] 数组的 OrderedDictionary 条目值的值?

c# - 将多个收藏品合并为一个

c# - protobuf-net 版本 2.X 到 3.X 迁移

c# - protobuf-net 什么时候需要使用 ProtoEnum 属性?