3

私はシリアライズしてから、Protobuf-net バージョン r431 (おそらく 1 年ほど前) を使用してデシリアライズするクラスを持っています。このクラスには、列挙型_typeと という文字列が含まれています_band。コンストラクターで_typeは、StationType.Other に_band設定され、空の文字列に設定されます。

ご覧のとおり、データを使用してオブジェクトを作成し、シリアル化してから逆シリアル化します。列挙型_type(StationType.Streaming) の値は失われますが、_band(FM) は保持されます。

動作に一貫性がないため、これはエラーだと思います。ただし、0 ではなく 1 の値から列挙を開始すると、すべてが期待どおりに機能します (たとえば、すべての値が保持されます)。

ここで何か不足していますか?以下のコードと出力を参照してください。

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が見つかりました。同じ問題を見ているかどうかはわかりません。修正されたかどうかは定かではありません。

4

2 に答える 2

9

これがグリッチです:

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(...)etcを使用します-ただし、キャッシュされたリフレクション/メタプログラミング出力がすべて含まれているため、このようなモデルを保存して再利用する必要があることに注意してください(何かをシリアル化する必要があるたびに再作成しないでください)。

于 2012-07-18T07:26:57.460 に答える
0

列挙型をマークしてください[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
    }
于 2012-07-18T00:03:30.250 に答える