Как сохранить массив с нулевым значением в Protobuf-Net?



Я нахожусь в процессе перехода от BinaryFormatter к Protobuf-net (который до сих пор, кажется, предлагает огромные улучшения как с точки зрения размера хранилища, так и времени десериализации).



Проблема, с которой я столкнулся, однако, это двойная?массивы не десериализуются в том же виде, в каком они были сериализованы. Любые значения в массиве, которые являются null, удаляются полностью - т. е. если я начинаю с массива с 6 элементами [null, null, 1, 2, 3, null], то после десериализации я получаю массив [1, 2, 3]. Для моей программы важно, чтобы я восстановил эти массивы в точно такой же форме, в какой они были до сериализации - как это произошло бы, если бы использовалась BinaryFormatter.



Одно решение, которое я придумал до сих пор, состоит в том, чтобы создать два массива для каждого, один из double [], где каждый элемент имеет значение, и один из bool [], который может быть использован для описания, если исходное значение было null - однако это очень неэффективно по разным причинам.



Я мог видеть упомянутое в предыдущем вопросе, связанном с тем, что может быть опция "SupportNull" для Протомембера, но я не смог найти никакой документации, ясно показывающей, как это реализовать, и не мог решить это сам, играя вокруг.



Любая помощь, которую кто-либо может предложить, будет чрезвычайно оценена.

572   2  

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);
        }
    }
}

На самом деле это не поддерживает, что из коробки, вы должны были бы манипулировать RuntimeTypeModel, чтобы явно установить, что он должен разрешить nulls.

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; }
    }

Comments

    Ничего не найдено.