1

私はC++/CLIで次のように定義されたクラスを持っています:

literal Int32 BufferLength = 4000;

Message()
{
   num1 = 0;
   num2 = 0;
   str1 = String::Empty;
   buffer = gcnew array<System::SByte>(BufferLength);
};

[ProtoMember(1)]
property double num1
{
   double get() { return _num1; }
   void set(double value) { _num1 = value; }
}

[ProtoMember(2)]
property double num2
{
   double get() { return _num2; }
   void set(double value) { _num2 = value; }
}

[ProtoMember(3)]
property String^ str1
{
   String^ get() { return _str1; }
   void set(String^ value) { _str1 = value; }
}

[ProtoMember(4)]
property array<System::SByte>^ buffer
{
   array<System::SByte>^ get() { return _buffer; }
   void set(array<System::SByte>^ value) { _buffer = value; }
}

デバッグ中に、シリアライザーがデータをそのままにしてバッファープロパティから値を取得しているのを確認できます。デシリアライザーを実行すると、データがバッファープロパティにプッシュされますが、シリアル化前に存在していたデータの代わりに、配列が0で埋められます。ProtoMember属性でIsRequired=trueを設定しようとしましたが、うまくいきませんでした。

正常に逆シリアル化されているsbyte配列で定義された他のメッセージがあります。ただし、これらのアレイは非常に短いです(最大10)。ここで私が目立つのは、この配列の長さだけです。ヘルプ!:-)

編集:私はv1r282を使用していることにも言及する必要があると思います。

4

1 に答える 1

1

ここでのエラーは、protobuf-net(protobuf-specに沿ったもの)がデータを追加することによってリスト(など)データを逆シリアル化することです。また、「v1」(使用しているバージョン)では、常にコンストラクターが実行されます。したがって、逆シリアル化するときは、コンストラクターを実行し(配列の長さ4000を作成)、データを処理して、さらに4000個のアイテムを追加します。チェックすると、配列の長さが8000になっていることがわかります(配列のサイズが4000倍にならないことを聞いてうれしいです...)。

修正:

  • v2では(実際には完全にはリリースされていません。これは情報提供のみを目的としています)、コンストラクターを完全に抑制することができます。
  • または、ctorで配列の作成を削除し、代わりにセットを介して割り当てます(おそらく、コードを節約するために、これを行う静的ファクトリメソッドを追加します)

次のテストリグ(私の便宜のためにC#に変換されました。申し訳ありません)は正常に機能します。

using System;
using System.Diagnostics;
using ProtoBuf;

namespace ConsoleApplication28
{
    class Program
    {
        static void Main()
        {
            var msg = Message.Create();
            var rand = new Random();
            var buffer = msg.buffer;
            for (int i = 0; i < buffer.Length; i++)
                buffer[i] = (sbyte)rand.Next(-128, 128);
            var clone = Serializer.DeepClone(msg);
            var cloneBuffer = clone.buffer;
            Debug.Assert(!ReferenceEquals(buffer, cloneBuffer), "Should be different buffer");

            Debug.Assert(buffer.Length == cloneBuffer.Length, "Should be same length");
            for(int i = 0 ; i < buffer.Length ; i++)
                Debug.Assert(buffer[i] == cloneBuffer[i], "Should be same value at index " + i);
        }
    }

    [ProtoContract]
    public class Message
    {
        const int BufferLength = 4000;
        public static Message Create()
        {
            var msg = new Message();
            msg.buffer = new sbyte[BufferLength];
            return msg;
        }
        private Message()
        {
           num1 = 0;
           num2 = 0;
           str1 = String.Empty;
        }


        private double _num1, _num2;
        private string _str1;
        private sbyte[] _buffer;

        [ProtoMember(1)]
        public double num1
        {
            get { return _num1; }
            set { _num1 = value; }
        }

        [ProtoMember(2)]
        public double num2
        {
           get { return _num2; }
           set { _num2 = value; }
        }

        [ProtoMember(3)]
        public String str1
        {
           get { return _str1; }
           set { _str1 = value; }
        }

        [ProtoMember(4)]
        public sbyte[] buffer
        {
           get { return _buffer; }
           set { _buffer = value; }
        }    
    }
}
于 2010-08-19T21:00:24.187 に答える