我正在从BinaryFormatter迁移到Protobuf-net(到目前为止,它似乎在存储大小和反序列化时间方面都提供了巨大的改进)。
然而,我遇到的一个问题是double?[]数组不会以序列化的相同形式反序列化。数组中任何null的值都会被全部删除 - 即如果我从一个包含6个元素[null,null,1,2,3,null]的数组开始,在反序列化后我最终会得到一个数组[1 ,2,3]。对于我的程序,我必须以与序列化之前完全相同的形式检索这些数组 - 就像使用BinaryFormatter时一样。
我到目前为止提出的一个解决方案是为每一个创建两个数组,一个是double [],其中每个元素都有一个值,另一个是bool [],可以用来描述原始值是否为null - 但是由于各种原因,这是非常低效的。
我可以在之前的相关问题中看到,ProtoMember可能有一个'SupportNull'选项,但我找不到任何文档清楚地显示如何实现这一点,并且无法通过游戏来解决这个问题。
任何人都可以提供的帮助将非常感激。
答案 0 :(得分: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; }
}
答案 1 :(得分: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);
}
}
}