protobuf-net不反序列化sbyte数组

时间:2010-08-19 16:23:18

标签: c++-cli protobuf-net

我有一个在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个)。这里唯一突出的是这个数组的长度。救命! : - )

编辑:我想我还应该提一下,我正在使用v1 r282。

1 个答案:

答案 0 :(得分:1)

这里的错误是protobuf-net(与protobuf-spec一致)通过追加数据反序列化列表(etc)数据。在“v1”(您使用的版本)中,它始终运行构造函数。因此,在反序列化时,它运行构造函数(创建数组长度4000),然后处理数据,追加另外4000个项目。如果你检查,你会发现阵列现在是8000长(你会很高兴听到它没有调整阵列4000次......)。

修正:

  • 在v2中(并非真正发布,仅供参考)您可以完全禁止构造函数
  • 或者只是删除ctor中的数组创建,然后通过set分配(也许添加一个静态工厂方法为你做这个,为你节省一些代码)

以下测试装备(为方便起见,翻译为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; }
        }    
    }
}