我有一个我序列化的类,然后使用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
编辑:在protobuf-net网站上找到issue 251,不确定我是否正在查看同一个问题。不太确定它是否已被修复。
答案 0 :(得分:8)
这是故障:
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(...)
等 - 但请注意,您应该存储并重新使用这样的模型(每次需要序列化时都不要重新创建它),因为它包含所有缓存的反射/元 - 编程输出。
答案 1 :(得分:0)
请使用[EnumMember]
e.g:
[DataContract]
[ProtoContract]
public enum StationType
{
[EnumMember]
[ProtoEnum(Name = "Streaming", Value = 0)]
Streaming = 0,
[EnumMember]
[ProtoEnum(Name = "Terrestrial", Value = 1)]
Terrestrial = 1,
[EnumMember]
[ProtoEnum(Name = "Other", Value = 2)]
Other = 2,
[EnumMember]
[ProtoEnum(Name = "Group", Value = 3)]
Group = 3
}