2

protobuf-netでは、次のProtoEnumAttributeように列挙のワイヤ形式をオーバーライドできます。

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

これらの属性を使用すると、通常はどこにDefaultシリアル化され、どこにシリアル化され、それぞれにシリアル化されるようになります。0Foo1110

私がやろうとしているのは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に、モデルに新しいものを追加するように指示します。2 行目は、その型の表現に必要な値を持つ 2 つのメンバーを追加します。false

それがうまくいかない場合 (そして、今日後で確認しようとします)、私に知らせてください。うまくいくようにします(または、同等の API を提供します)。属性なしで作業しているときに、このシナリオを検証することができなかっただけかもしれません。

于 2012-12-09T08:52:19.860 に答える