3

私は BinaryFormatter から Protobuf-net に移行中です (これまでのところ、ストレージ サイズと逆シリアル化時間の両方の点で大幅な改善が見られます)。

しかし、私が遭遇した問題は、 double?[] 配列がシリアル化されたのと同じ形式で逆シリアル化されないことです。null である配列内の値はすべて削除されます。つまり、[null、null、1、2、3、null] の 6 つの要素を持つ配列で開始すると、逆シリアル化後に [1 の配列になります。 、2、3]。私のプログラムでは、BinaryFormatter を使用した場合と同様に、シリアル化前とまったく同じ形式でこれらの配列を取得することが不可欠です。

私がこれまでに思いついた解決策の 1 つは、すべての要素に対して 2 つの配列を作成することです。1 つはすべての要素に値がある double[] の配列で、もう 1 つは元の値が null であったかどうかを記述するために使用できる bool[] の配列です。ただし、これは、さまざまな理由で非常に非効率的です。

以前の関連する質問で、ProtoMember に「SupportNull」オプションがある可能性があると言及されていましたが、これを実装する方法を明確に示しているドキュメントを見つけることができず、遊んで自分で解決できませんでした。

誰もが提供できるどんな助けも大歓迎です。

4

2 に答える 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);
        }
    }
}
于 2013-10-01T09:43:54.307 に答える
2

実際にはそのままではサポートされていませんRuntimeTypeModel。null を許可するように明示的に設定するには、 を操作する必要があります。

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; }
    }
于 2013-10-01T09:09:03.980 に答える