C# 如何在Protobuf Net中持久化一个可为空值的数组?

C# 如何在Protobuf Net中持久化一个可为空值的数组?,c#,serialization,persistence,deserialization,protobuf-net,C#,Serialization,Persistence,Deserialization,Protobuf Net,我正在从BinaryFormatter迁移到Protobuf net(到目前为止,它似乎在存储大小和反序列化时间方面都提供了巨大的改进) 但是,我遇到的一个问题是,double?[]数组的反序列化形式与它们序列化时的形式不同。数组中的任何空值都将被全部删除-即,如果我从一个包含6个元素[null,null,1,2,3,null]的数组开始,反序列化后我将以[1,2,3]的数组结束。对于我的程序,我必须以序列化之前完全相同的形式检索这些数组——如果使用BinaryFormatter,就会发生这种情

我正在从BinaryFormatter迁移到Protobuf net(到目前为止,它似乎在存储大小和反序列化时间方面都提供了巨大的改进)

但是,我遇到的一个问题是,double?[]数组的反序列化形式与它们序列化时的形式不同。数组中的任何空值都将被全部删除-即,如果我从一个包含6个元素[null,null,1,2,3,null]的数组开始,反序列化后我将以[1,2,3]的数组结束。对于我的程序,我必须以序列化之前完全相同的形式检索这些数组——如果使用BinaryFormatter,就会发生这种情况

到目前为止,我提出的一个解决方案是为每一个数组创建两个数组,一个是double[],其中每个元素都有一个值,另一个是bool[],可以用来描述原始值是否为null,但是由于各种原因,这是非常低效的

我可以在前面的相关问题中看到,ProtoMember可能有一个“SupportNull”选项,但我找不到任何文档清楚地说明如何实现这一点,我自己也无法通过玩来解决这个问题


任何人能提供的任何帮助都将不胜感激。

它实际上不支持开箱即用,您必须操纵
RuntimeTypeModel
来显式设置它应该允许空值

RuntimeTypeModel.Default[typeof(YourObjectType)][(tag)]。SupportNull=true

例如:

var nullable = new ObjectWithNullables() { IntArray = new int?[] { null, 1, 2, null } };

// returns 2 elements out of 4
//var resultA = Deserialize<ObjectWithNullables>(Serialize<ObjectWithNullables>(nullable));

RuntimeTypeModel.Default[typeof(ObjectWithNullables)][1].SupportNull = true;

// returns 4 elements out of 4
var resultA = Deserialize<ObjectWithNullables>(Serialize<ObjectWithNullables>(nullable));


    [ProtoContract]
    public class ObjectWithNullables
    {
        [ProtoMember(1)]
        public int?[] IntArray { get; set; }
    }
var nullable=newobjectwithnullables(){IntArray=newint?[]{null,1,2,null};
//返回4个元素中的2个
//var resultA=反序列化(序列化(可空));
RuntimeTypeModel.Default[typeof(ObjectWithNullables)][1]。SupportNull=true;
//返回4个元素中的4个
var resultA=反序列化(序列化(可空));
[原始合同]
公共类ObjectWithNullables
{
[原成员(1)]
公共int?[]IntArray{get;set;}
}

@user2262704添加了一个例子来说明我的意思事实上,它确实支持这一点。@MarcGravel刚刚找到了相同的解决方案^^更新了我的答案感谢Marc提供了出色的示例。但是如果有一个属性就好了。实际上,在反序列化时并不总是调用静态构造函数中的设置。然后我们必须将“SupportNull”设置在类之外的其他位置。但这样做违背了良好编程的主要原则:高内聚和低耦合。
using ProtoBuf;
using ProtoBuf.Meta;
using System;
[ProtoContract]
class Foo
{
    [ProtoMember(1)]
    public double?[] Values { get; set; }
}
static class Program
{
    static void Main()
    {
        // configure the model; SupportNull is not currently available
        // on the attributes, so need to tweak the model a little
        RuntimeTypeModel.Default.Add(typeof(Foo), true)[1].SupportNull = true;

        // invent some data, then clone it (serialize+deserialize)
        var obj = new Foo { Values = new double?[] {1,null, 2.5, null, 3}};
        var clone = Serializer.DeepClone(obj);

        // check we got all the values back
        foreach (var value in clone.Values)
        {
            Console.WriteLine(value);
        }
    }
}