繁体   English   中英

ProtoBuf-net序列化包含列表的对象时无效行为

[英]ProtoBuf-net invalid behaviour when serializing object containing list

我很难尝试在以下示例中解释行为:

[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);
    }

我的期望是originalDatadeserializedData应该相同。 它们主要是deserializedData.arr[0].data1 == 1 while originalData.arr[0].data1 == 0 所有其他对象都是相同的,甚至包括originalData.arr[0].data2 and deserializedData.arr[0].data2 (字符串字段)。

protobuf-net假定“隐式默认为零”-即,除非另有特定说明,否则成员的默认值为零,这意味着:不传输零。 这并非纯粹是任意的-实际上是“ proto3”规范(好吧...或多或少;在“ proto3”中,零是唯一允许的默认值)。

您的代码(尤其是属性初始化器)的行为就像默认值为1,因此:当不传输零时,构造函数仍会应用1,而该值将变为值(protobuf中的反序列化是“合并”操作-保留先前存在的值(再次符合规范)。

选项:

  • 告诉protobuf-net您的默认值-将[DefaultValue(1)]到属性中
  • 告诉protobuf-net不要运行构造函数(和属性初始化程序)-将SkipConstructor = true添加到[ProtoContract]
  • 告诉protobuf-net不要假定此行为: RuntimeTypeModel.Default.ImplicitZeroDefault = false;
  • 添加您自己的条件序列化回调(如果您确实想要,我可以举个例子)

我个人会使用第一个选项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM