问题
I am in the process of migrating from BinaryFormatter to Protobuf-net (which so far appears to offer HUGE improvements both in terms of storage size and deserialization time).
A problem I've encountered however is that double?[] arrays do not deserialize in the same form they were serialized. Any values in the array that are null get removed in their entirety - i.e. if I start with an array with 6 elements of [null, null, 1, 2, 3, null], after deserialization I end up with an array of [1, 2, 3]. For my programme, it is essential that I retreive these arrays in exactly the same form they were prior to serialization - as would happen if BinaryFormatter were used.
One solution I have come up with so far is to create two arrays for every one, one of double[] where every element has a value, and one of bool[] which can be used to describe if the original value was null - however this is very inefficient for various reasons.
I could see mentioned in a previous related question that there may be a 'SupportNull' option for a ProtoMember, but I couldn't find any documentation showing clearly how to implement this, and could not work it out myself by playing around.
Any help anyone could offer would be hugely appreciated.
回答1:
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);
}
}
}
回答2:
It actually doesn't support that out of the box, you would have to manipulate the RuntimeTypeModel to explicitly set that it should allow nulls.
RuntimeTypeModel.Default[typeof(YourObjectType)][(tag)].SupportNull = true;
Example:
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; }
}
来源:https://stackoverflow.com/questions/19112122/how-can-i-persist-an-array-of-a-nullable-value-in-protobuf-net