2

protobuf-net中,您可以使用以下方式覆盖枚举的有线格式ProtoEnumAttribute

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

使用这些属性,Default通常将序列化到0Foo到的位置1现在将分别序列化到110

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

挖掘 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++;
}

但是我不能依靠反射到一个私有(只读!)字段来发送这个,这只是自找麻烦。

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

4

1 回答 1

2

我不在 PC 上检查这个,所以如果我在胡说八道,你必须纠正我,但它应该是这样的(在应用程序的早期):

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

第一行告诉它Type在模型中添加一个新的,而不是( false) 应用任何通常的规则;第二行将 2 个成员添加到该类型的表示中,并带有所需的值。

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

于 2012-12-09T08:52:19.860 回答