在下面的示例中,我很难解释行为:
[ProtoContract]
public class Class1Proto
{
[ProtoMember(1)]
public int data1 = 1;
[ProtoMember(2)]
public string data2 = "MYRANDOMSTRING";
}
[ProtoContract]
public class ProtoChunk
{
[ProtoMember(1)]
public List<Class1Proto> arr = new List<Class1Proto>();
public const int PageSize = 4096;
}
用法:
byte[] page = new byte[ProtoChunk.PageSize];
ProtoChunk originalData = new ProtoChunk();
for (int i = 0; i < 100; i++)
{
Class1Proto p = new Class1Proto();
p.data1 = i * 2;
p.data2 = (i * 2).ToString();
originalData.arr.Add(p);
}
using (var memStream = new MemoryStream(page, writable:true))
{
Serializer.SerializeWithLengthPrefix(memStream, originalData, PrefixStyle.Fixed32);
}
using (var memStream = new MemoryStream(page, writable:false))
{
ProtoChunk deserializedData = Serializer.DeserializeWithLengthPrefix<ProtoChunk>(memStream, PrefixStyle.Fixed32);
}
我期望originalData
和deserializedData
应该相同。并且大多数除deserializedData.arr[0].data1 == 1 while originalData.arr[0].data1 == 0
以外。所有其他对象都是相同的,甚至包括originalData.arr[0].data2 and deserializedData.arr[0].data2
(字符串字段)。
答案 0 :(得分:3)
protobuf-net假定“隐式默认值为零”-即,除非另有说明,否则成员的默认值均为零,这意味着:不会传输零。这并非纯粹是任意的-实际上是“ proto3”规范(好吧,或多或少;在“ proto3”中,零是 only 允许的默认值)。
您的代码-尤其是属性初始化器-的行为就像它的默认值为1,因此:当不传输零时,构造函数仍会应用1,而该值将变为值(protobuf中的反序列化是“合并”操作-再次保留符合规范的预先存在的值。
选项:
[DefaultValue(1)]
添加到媒体资源SkipConstructor = true
添加到[ProtoContract]
RuntimeTypeModel.Default.ImplicitZeroDefault = false;
我会亲自使用第一个选项。