Как сохранить массив с нулевым значением в Protobuf-Net?
Я нахожусь в процессе перехода от BinaryFormatter к Protobuf-net (который до сих пор, кажется, предлагает огромные улучшения как с точки зрения размера хранилища, так и времени десериализации).
Проблема, с которой я столкнулся, однако, это двойная?массивы не десериализуются в том же виде, в каком они были сериализованы. Любые значения в массиве, которые являются null, удаляются полностью - т. е. если я начинаю с массива с 6 элементами [null, null, 1, 2, 3, null], то после десериализации я получаю массив [1, 2, 3]. Для моей программы важно, чтобы я восстановил эти массивы в точно такой же форме, в какой они были до сериализации - как это произошло бы, если бы использовалась BinaryFormatter.
Одно решение, которое я придумал до сих пор, состоит в том, чтобы создать два массива для каждого, один из double [], где каждый элемент имеет значение, и один из bool [], который может быть использован для описания, если исходное значение было null - однако это очень неэффективно по разным причинам.
Я мог видеть упомянутое в предыдущем вопросе, связанном с тем, что может быть опция "SupportNull" для Протомембера, но я не смог найти никакой документации, ясно показывающей, как это реализовать, и не мог решить это сам, играя вокруг.
Любая помощь, которую кто-либо может предложить, будет чрезвычайно оценена.
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