32

空のリストのシリアル化にはいくつかの問題があります。CF 2.0 を使用した .NET のコード

//Generating the protobuf-msg
ProtoBufMessage msg = new ProtoBufMessage();
msg.list = new List<AnotherProtobufMessage>();
// Serializing and sending throw HTTP-POST
MemoryStream stream = new MemoryStream();
Serializer.Serialize(stream, msg);
byte[] bytes = stream.ToArray();
HttpWebRequest request = createRequest();
request.ContentLength = bytes.Length ;

using (Stream httpStream = request.GetRequestStream())
{              
      httpStream.Write(bytes, 0, bytes.Length);
}

ストリームに書き込もうとすると例外が発生しました (bytes.length が範囲外)。しかし、空の List を持つ型は 0 バイトであってはなりませんよね (型情報?)?

応答にはクライアントへのサーバーからのメッセージがあるため、このタイプの送信が必要です。

4

3 に答える 3

38

ワイヤ形式 (Google によって定義されています - 私のコントロール内ではありません!) は、アイテムのデータのみを送信します。のリストと空のリストを区別しません。したがって、送信するデータがない場合 - はい、長さは 0 です (非常に倹約的な形式です ;-p)。

プロトコル バッファには、ワイヤ上の型メタデータは含まれません。

ここでのもう 1 つのよくある落とし穴は、リスト プロパティが自動的に空としてインスタンス化されると想定するかもしれませんが、そうではないということです (おそらくフィールド初期化子またはコンストラクターでコードがそうしない限り)。

実行可能なハックは次のとおりです。

[ProtoContract]
class SomeType {

    [ProtoMember(1)]
    public List<SomeOtherType> Items {get;set;}

    [DefaultValue(false), ProtoMember(2)]
    private bool IsEmptyList {
        get { return Items != null && Items.Count == 0; }
        set { if(value) {Items = new List<SomeOtherType>();}}
    }
}

ハックかもしれませんが、うまくいくはずです。必要に応じて「セット」を失い、Items単にドロップすることもできますbool

    [ProtoMember(1)]
    public List<SomeOtherType> Items {get {return items;}}
    private readonly List<SomeOtherType> items = new List<SomeOtherType>();

    [DefaultValue(false), ProtoMember(2)]
    private bool IsEmptyList {
        get { return items.Count == 0; }
        set { }
    }
于 2010-03-04T13:01:06.607 に答える
0
public List<NotificationAddress> BccAddresses { get; set; }

次のように置き換えることができます:

private List<NotificationAddress> _BccAddresses;
public List<NotificationAddress> BccAddresses {
   get { return _BccAddresses; }
   set { _BccAddresses = (value != null && value.length) ? value : null; }
}
于 2015-06-12T13:20:27.047 に答える