代码之家  ›  专栏  ›  技术社区  ›  Klark

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

  •  0
  • Klark  · 技术社区  · 6 年前

    我很难用下面的例子来解释行为:

    [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 (字符串字段)。

    1 回复  |  直到 6 年前
        1
  •  3
  •   Marc Gravell    6 年前

    protobuf-net假设“隐式零缺省值”——即,除非另有规定,否则成员的缺省值为零,这意味着:不传输零。这不是纯粹的武断-这实际上是“proto3”规范(嗯。。。或多或少;在“proto3”中,零是 只有 允许的违约)。

    选项:

    • 告诉protobufnet你的默认添加 [DefaultValue(1)] 到物业
    • 告诉protobuf net不要运行构造函数(和属性初始值设定项)-add SkipConstructor = true [ProtoContract]
    • 告诉protobuf net不要假设这种行为: RuntimeTypeModel.Default.ImplicitZeroDefault = false;
    • 添加您自己的条件序列化回调(如果您真的需要,我可以给出一个示例)