3

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

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

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

我可以看到在之前的相关问题中提到,ProtoMember 可能有一个“SupportNull”选项,但我找不到任何文档清楚地显示如何实现这一点,并且无法自己解决。

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

4

2 回答 2

2

它实际上不支持开箱即用,您必须操纵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; }
    }
于 2013-10-01T09:09:03.980 回答
2
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);
        }
    }
}
于 2013-10-01T09:43:54.307 回答