gpt4 book ai didi

c# - 使用 protobuf-net 序列化 [Flags] 枚举时出现 InvalidOperationException

转载 作者:行者123 更新时间:2023-11-30 18:17:01 37 4
gpt4 key购买 nike

我正在尝试序列化一个用 [Flags] 属性修饰的 enum 类型。 enum声明如下:

[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,
}

现在,当我尝试序列化容器对象时,我得到了

InvalidOperationException:Operation is not valid due to the current state of the object.

在 SO 上的其他类似帖子之后,我尝试了以下操作:

  1. 在我的枚举的 ProtoContract 属性中添加 EnumPassthru = true 参数
  2. 在应用程序启动阶段使用 RuntimeTypeModel.Default[typeof(Categories)].EnumPassthru = true;
  3. 为容器对象的枚举值字段提供了 IsRequired 参数 [ProtoMember(6, IsRequired = true)]

我的枚举声明还有什么遗漏的吗?

异常细节的开头是这样的:

InvalidOperationException:Operation is not valid due to the current state of the object.\r\n at ProtoBuf.Serializers.EnumSerializer.EnumToWire(Object value) in c:\Users\onur.gumus\Desktop\protobuf-net-master\protobuf-net\Serializers\EnumSerializer.cs:line 83\r\n at ProtoBuf.Serializers.EnumSerializer.Write(Object value, ProtoWriter dest) in c:\Users\onur.gumus\Desktop\protobuf-net-master\protobuf-net\Serializers\EnumSerializer.cs:line 125\r\n at ProtoBuf.Serializers.FieldDecorator.Write(Object value, ProtoWriter dest) in c:\Users\onur.gumus\Desktop\protobuf-net-master\protobuf-net\Serializers\FieldDecorator.cs:line 38\r\n at ProtoBuf.Serializers.TypeSerializer.Write(Object value, ProtoWriter dest) in c:\Users\onur.gumus\Desktop\protobuf-net-master\protobuf-net\Serializers\TypeSerializer.cs:line 173\r\n at ProtoBuf.Meta.TypeModel.TrySerializeAuxiliaryType(ProtoWriter writer, Type type, DataFormat format, Int32 tag, Object value, Boolean isInsideList) in c:\Users\onur.gumus\Desktop\protobuf-net-master\protobuf-net\Meta\TypeModel.cs:line 125 ...

最佳答案

在所有容易获得的(即不是古老的)版本的 protobuf-net 中,[Flags] 将激活直通行为,使这项工作正常进行。 [ProtoContract(EnumPassThru = true)]激活直通行为,但如果指定了 [Flags],则它是多余的。

在 2.3.0 及更高版本中,传递行为也是默认,只要您没有[ProtoEnum] 属性实际上改变了序列化值(你的没有)——这是为了与“proto3”更加一致,并且在绝大多数情况下更容易使用枚举。

所以:这里没有必要做任何 - 您的代码应该已经可以正常工作了。

我试过你的代码:

  • 使用 2.3.0 和 2.0.0.668
  • 使用问题中的属性,并删除除 [Flags] 之外的所有内容
  • 在 2.3.0 上,甚至删除了 [Flags] 属性(尽管我同意它应该保留在你的情况下——这绝对是一个 [Flags] 枚举)
  • 以枚举作为根值,并以枚举作为成员,在传入的对象上标记为[ProtoMember]

在所有情况下它都运行良好。所以:在一般情况下,我只能说你所拥有的应该已经可以工作了

如果它在特定情况下失败,最好在问题中包含一个完整的可运行示例(最好告诉我们您正在运行的框架),这样我们就可以看到什么你看到了。这很好用,例如:

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);
}
}

关于c# - 使用 protobuf-net 序列化 [Flags] 枚举时出现 InvalidOperationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45220365/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com