3

私は'No parameterless constructor found for [type]'過去数時間、例外に苦労してきました。ここで、アプリケーションにあるものを反映する単純な単体テストを作成しました。実行しないと、この例外がスローされるようですstream.Position = 0

また、オブジェクトが単なる標準クラス (抽象クラスから派生したものではない) である場合、この例外は発生しません。

以下のコードを参照してください。

  1. そのまま実行 - Base のコンストラクターが見つからないと言って壊れます

  2. stream.Position = 0 のコメントを外してください。

  3. 行を再度コメントアウトし、Derived クラスを Base から継承しないように変更し、クラス内の唯一のプロパティのコメントを外して実行します - 壊れません (ただし、明らかに Name は null になります)

誰かがなぜこれがこのように機能するのか説明できますか? #1 がスローする理由 (または #3 がスローしない理由) と、このメッセージの理由は?

[Test]
public void CanSerialize_Derived()
{
    var derived = new Derived() {Name = "ngf"};
    var stream = new MemoryStream();
    Serializer.Serialize(stream, derived);
    //stream.Position = 0;
    var deserializedInstance = Serializer.Deserialize<Derived>(stream);
}

[ProtoContract]
[ProtoInclude(9, typeof(Derived))]
public abstract class Base 
{
    [ProtoMember(1)]
    public string Name { get; set; }
}

[ProtoContract]
public class Derived : Base
{
    //[ProtoMember(1)]
    //public string Name { get; set; }
}
4

1 に答える 1

5

長さゼロのストリームは protobuf-net で有効です。protobuf-net では、すべてのシリアライゼーションはその DTO 継承ツリーのルート タイプから開始されるため、データに実際に が含まれていることに同意Baseできるまで、信じられず、. だから1番投げる。DerivedBase

明らかに、最後にストリームを残すと、デシリアライズできるデータの長さはゼロになります。これが#2が合格する理由です。

継承を削除すると、その継承ツリーのルートはDerived; abstractこれは根本的に破壊的な変更ですが、継承に関する違いは、情報なしで型を逆シリアル化しようとしていないことです。そのため、#3で修正します(悪い理由で)。

ここで重要なことは、継承が情報として実装されていることです。情報がない限り、オブジェクトが継承ツリーのルートにある型であると仮定するだけです。

于 2013-03-04T20:08:23.527 に答える