4

protobuf-netを使用した逆シリアル化に問題があります。

私は次のクラスを持っています:

[ProtoContract]
public class CrazyList : List<string>
{
    [ProtoMember(1)]
    private readonly string _foo;

    public CrazyList(string foo)
    {
        _foo = foo;
    }

    public CrazyList(){}

    public new void Add(string item)
    {
        Console.Write(item + foo); // Problem is here!

        base.Add(item);
    }

}

そして、次のように使用します。

var list = new CrazyList("world!");
list.Add("Hello ");

using (var ms = new MemoryStream())
{
    Serializer.Serialize(ms, list);

    ms.Position = 0;

    var listDS = Serializer.Deserialize<CrazyList>(ms);
    listDS.Add("Goodbye ");
}

このメソッドは、フィールドの逆シリアル化が完了Addする前に実行されます。_foo

どうすればこの問題を解決できますか?

4

2 に答える 2

1

これをCrazList属性に使用する必要があります。

[ProtoBuf.ProtoContract(IgnoreListHandling=true)]
于 2012-11-28T19:28:29.830 に答える
1

XmlSerializerと同様に、何かリストであるかリーフです。「両方」はありません。現時点では、「リスト」を検出し、リーフメンバーを検索しません。リーフに変更することはできますが(Fredouの回答を参照)、アイテムはシリアル化されません。

ワイヤーの仕様(私ではなくグーグルによる)のため、リスト自体の表現はありません繰り返されるシーケンスは、「アイテム、アイテム、アイテム、アイテム」です。したがって、何かがリストである場合、リスト自体に関連するデータを保存できる場所は文字通りありません。

率直に言って、最も簡単なオプションは、カプセル化するためにリファクタリングすることです(簡潔にするために最小限に抑えます)。

class SomeWrapper {
    string Foo ...
    List<string> Items ... 
}

Fredouが示すアプローチを使用し、次のように追加することで、必要に応じてチートすることもできます。

[ProtoMember(2)]
private IList<string> Items { get { return this; } }

これにより、実際にモデルを大幅に変更することなく、上記の最小限の例のようになります

List<T>ちなみに、サブクラスにカスタムAddを提供することはお勧めしません。また、逆シリアル化の順序に依存しないでください。

于 2012-11-28T20:45:46.130 に答える