问题
In protobuf-net, you can override the wire format for enumerations with the ProtoEnumAttribute
like so:
[ProtoContract]
enum MyEnum
{
[ProtoEnum(Value=1)]
Default,
[ProtoEnum(Value=10)]
Foo
}
With those attributes, where Default
would normally serialize to 0
and Foo
to 1
they will now serialize to 1
and 10
respectively.
What I'm trying to do is mimic this behavior using interfaces in ProtoBuf.Meta, so I don't have to annotate enumerations (because I don't typically control them in my project).
Digging through protobuf-net's source, I've managed to get the following (simplified a bit) working:
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++;
}
However I can't ship this relying on reflecting into a private (readonly!) field, that's just asking for trouble.
So, is there a supported way to override enumeration wire values at runtime in protobuf-net?
回答1:
I'm not at a PC to check this, so you'll have to correct me if I'm making crazy-talk, but it should be something like (early on in the app):
RuntimeTypeModel.Default.Add(typeof(MyEnum), false)
.Add(1, "Default").Add(10, "Foo");
The first line tells it to add a new Type
to the model, without (false
) applying any of the usual rules; the second line adds 2 members to that type's representation, with the required values.
If that doesn't work (and I'll try to check later today), let me know and I'll make it work (or provide an equivalent API). It could just be that this scenario simply hasn't come up for me to verify it when working without attributes.
来源:https://stackoverflow.com/questions/13783894/mimic-protoenumattribute-with-protobuf-meta-interface