我有一个在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。
答案 0 :(得分:1)
这里的错误是protobuf-net(与protobuf-spec一致)通过追加数据反序列化列表(etc)数据。在“v1”(您使用的版本)中,它始终运行构造函数。因此,在反序列化时,它运行构造函数(创建数组长度4000),然后处理数据,追加另外4000个项目。如果你检查,你会发现阵列现在是8000长(你会很高兴听到它没有调整阵列4000次......)。
修正:
以下测试装备(为方便起见,翻译为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; }
}
}
}