How can I persist an array of a nullable value in Protobuf-Net?

感情迁移 提交于 2019-12-10 10:12:37

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!