gpt4 book ai didi

c# - 为什么枚举不使用 protobufs 反序列化?

转载 作者:行者123 更新时间:2023-11-30 13:48:45 24 4
gpt4 key购买 nike

我有一个序列化的类,然后使用 Protobuf-net 版本 r431(可能已有一年左右)反序列化。该类包含一个枚举 _type 和一个名为 _band 的字符串。在构造函数中,_type 设置为 StationType.Other,_band 设置为空字符串。

如您所见,我创建了一个包含数据的对象,序列化,然后反序列化。枚举 _type (StationType.Streaming) 的值丢失,而 _band (FM) 保留。

我觉得这是一个错误,因为行为不一致。但是,如果我从值 1 而不是 0 开始枚举,一切都会按预期工作(例如,所有值都将保留)。

我是不是漏掉了什么?请参阅下面的代码和输出:

using System;
using System.IO;
using ProtoBuf;

namespace ProtoBufsWithEnums
{
class Program
{
static void Main(string[] args)
{
stn1 = new Station{Type = StationType.Streaming, Band = "FM"};

var ms1 = new MemoryStream();
Serializer.Serialize(ms1, stn1); // serialize
byte[] bytes = ms1.ToArray();

var ms2 = new MemoryStream(bytes);
Station stn2 = Serializer.Deserialize<Station>(ms2); // deserialize

Console.WriteLine("Type - Original {0}, New {1}", stn1.Type, stn2.Type);
Console.WriteLine("Band - Original {0}, New {1}", stn1.Band, stn2.Band);
}
}

[ProtoContract]
public enum StationType
{
[ProtoEnum(Name = "Streaming", Value = 0)]
Streaming = 0,
[ProtoEnum(Name = "Terrestrial", Value = 1)]
Terrestrial = 1,
[ProtoEnum(Name = "Other", Value = 2)]
Other = 2,
[ProtoEnum(Name = "Group", Value = 3)]
Group = 3
}

[ProtoContract]
public class Station
{
[ProtoMember(9)]
private StationType _type;
[ProtoMember(10)]
private string _band;

public Station()
{
_type = StationType.Other;
_band = "";
}

public StationType Type
{
get { return _type; }
set { _type = value; }
}

public string Band
{
get { return _band; }
set { _band = value; }
}
}
}

输出:

Type - Original Streaming, New Terrestrial
Type - Original FM, New FM

编辑:发现issue 251在 protobuf-net 站点上,不确定我是否正在查看相同的问题。不太确定它是否已修复。

最佳答案

这里是故障:

public Station()
{
_type = StationType.Other;
_band = "";
}

protobuf-net 对零默认值做了一些隐含的假设。这在很多情况下都很有效,但不是全部。在这里帮助它的最简单方法是告诉它您正在使用非零默认值:

[ProtoMember(9), DefaultValue(StationType.Other)]
private StationType _type;

另一种选择是告诉它始终序列化它:

[ProtoMember(9, IsRequired = true)]
private StationType _type;

如果您有很多,另一种选择是禁用“零默认”行为,这可以在自定义模型上完成:

var model = TypeModel.Create();
model.UseImplicitZeroDefaults = false;

然后使用 model.Serialize(...) 等 - 但请注意,您应该存储并重新使用这样的模型(不要在每次需要序列化某些内容时都重新创建它) ,因为它包含所有缓存的反射/元编程输出。

关于c# - 为什么枚举不使用 protobufs 反序列化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11532501/

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