繁体   English   中英

为什么enums不会使用protobufs进行反序列化?

[英]Why won't enums deserialize with protobufs?

我有一个我序列化的类,然后使用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网站上找到问题251 ,不确定我是否正在查看相同的问题。 不确定它是否已被修复。

这是故障:

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(...)等 - 但请注意,您应该存储并重新使用这样的模型(每次需要序列化时都不要重新创建它),因为它包含所有缓存的反射/元 - 编程输出。

请用[EnumMember]标记枚举

例如:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM