问题描述
我正在尝试序列化用 [Flags]
属性修饰的 enum
类型. enum
声明如下:
I am trying to serialize an enum
type that is decorated with [Flags]
attribute. The enum
declaration is as follows:
[Flags]
[ProtoContract(EnumPassthru = true)]
public enum Categories
{
[ProtoEnum(Name = nameof(Invalid), Value = 0x0)]
Invalid = 0x0,
[ProtoEnum(Name = nameof(A), Value = 0x1)]
A = 0x1,
[ProtoEnum(Name = nameof(B), Value = 0x2)]
B = 0x2,
[ProtoEnum(Name = nameof(C), Value = 0x4)]
C = 0x4,
[ProtoEnum(Name = nameof(D), Value = 0x8)]
D = 0x8,
[ProtoEnum(Name = nameof(Global), Value = 0x1 | 0x2 | 0x4 | 0x8)]
Global = A | B | C | D,
}
现在,当我尝试序列化容器对象时,我得到了
Now, when I try to serialize the container object, I get
在SO上的其他类似帖子之后,我尝试了以下操作:
Following other similar posts on SO, I have tried the following:
- 在我的枚举的ProtoContract属性中
- 添加
EnumPassthru = true
参数 - 在应用启动阶段使用
RuntimeTypeModel.Default [typeof(Categories)].EnumPassthru = true;
- 使用IsRequired参数
[ProtoMember(6,IsRequired = true)]
为容器对象的枚举值字段提供了内容
- Add
EnumPassthru = true
parameter in my enum's ProtoContract attribute - Use
RuntimeTypeModel.Default[typeof(Categories)].EnumPassthru = true;
at the app startup phase, - Provided the container object's enum-valued field with the IsRequired parameter
[ProtoMember(6, IsRequired = true)]
我的枚举声明还有其他想念的地方吗?
Is there anything else that I miss with my enum declaration?
异常详细信息的开头如下:
The beginning of the exception detail goes like:
推荐答案
在protobuf-net的所有容易获得的版本(即非古代)中, [Flags]
将激活直通行为,从而这项工作很好. [ProtoContract(EnumPassThru = true)]
也会 激活直通行为,但是如果指定了 [Flags]
,则是多余的.
In all easily available (i.e. not ancient) versions of protobuf-net, [Flags]
will activate pass-thru behaviour, making this work fine. [ProtoContract(EnumPassThru = true)]
will also activate pass-thru behaviour, but is redundant if [Flags]
is specified.
在2.3.0及更高版本中,只要您不具有实际更改序列化的值(但不要更改)-这与"proto3"更加一致,并且在大多数情况下可以更轻松地使用枚举.
In 2.3.0 and above, pass-thru behaviour is also assumed by default as long as you don't have any [ProtoEnum]
attributes that actually change the serialized value (which: yours do not) - this is to be more consistent with "proto3", and to make it easier to work with enums in the vast majority of cases.
所以:这里没有必要做任何事情-您的代码应该已经可以正常工作了.
So: it should not be necessary to do anything here - your code should already just work.
我已经尝试过您的代码:
I've tried your code:
- 具有2.3.0和2.0.0.668
- 带有问题中的属性,并删除了除
[Flags]
以外的所有内容 - 在2.3.0上,甚至删除了
[Flags]
属性(尽管我同意应保留在您的情况下-绝对是[Flags]
枚举) - 以枚举为根值,并以枚举作为成员,在传入的对象上标记为
[ProtoMember]
- with 2.3.0 and 2.0.0.668
- with the attributes in the question, and with everything except
[Flags]
removed - on 2.3.0 with even the
[Flags]
attribute removed (although I agree it should be retained in your case - that is definitely a[Flags]
enum) - with the enum as the root value, and with the enum as a member marked
[ProtoMember]
on an object passed in
在所有情况下都可以正常工作.所以:在一般情况下,我只能说你拥有的应该已经可以工作了.
In all cases it worked fine. So: in the general case, all I can say is that what you have should already work.
如果在特定的 情况下失败,那么在问题中包含完整的可运行示例(最好是告诉我们您正在运行的是什么框架)将是一个很好的选择,因此我们可以看到您正在看到.可以正常工作,例如:
If it is failing in a specific case, it would be great to include a full runnable sample in the question (ideally telling us exactly what framework you are running on), so we can see what you are seeing. This works fine, for example:
using ProtoBuf;
using System;
[Flags]
public enum Categories
{
Invalid = 0x0,
A = 0x1,
B = 0x2,
C = 0x4,
D = 0x8,
Global = A | B | C | D,
}
[ProtoContract]
public class X
{
[ProtoMember(1)]
public Categories Val { get; set; }
public override string ToString() => Val.ToString();
}
static class P
{
static void Main()
{
var orig = new X { Val = Categories.D | Categories.B };
var cloneObj = Serializer.DeepClone(orig);
Console.WriteLine(cloneObj);
var cloneEnum = Serializer.DeepClone(orig.Val);
Console.WriteLine(cloneEnum);
}
}
这篇关于使用protobuf-net序列化[Flags]枚举时,InvalidOperationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!