バイナリシリアル化の奇妙な動作に気づきました。クラスの辞書を逆シリアル化し、すぐに何かを追加しようとすると、完全に初期化されていないため、エラーが発生します。
[Serializable]
class Foo : ISerializable
{
public Dictionary<int, string> Dict { get; private set; }
public Foo()
{
Dict = new Dictionary<int, string>();
}
public Foo(SerializationInfo info, StreamingContext context)
{
Dict = (Dictionary<int, string>)info.GetValue("Dict", typeof(Dictionary<int, string>));
Dict.Add(99, "test"); // Error here
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Dict", Dict);
}
}
ディクショナリにデータを追加する行で、を取得しますNullReferenceException
が、Dict
プロパティはnullではありません。インスタンス化されますが初期化されません(すべてのフィールドが0またはnullです)。で作成されただけでFormatterServices.GetUninitializedObject
、実際にはまだ逆シリアル化されていないのではないかと思います。
この時点で、おそらく完全に初期化されていないことを理解しています。IDeserializationCallback
そこで、インターフェイスを実装することで、別のアプローチを試しました。MSDNによると:
オブジェクトグラフの逆シリアル化が完了したときに呼び出されるメソッドのサポートの一部として、現在のインターフェイスを実装します。
オブジェクトが子オブジェクトでコードを実行する必要がある場合、このアクションを遅らせ、IDeserializationCallbackを実装し、このインターフェイスでコールバックされたときにのみコードを実行できます。
だから、まさに私が必要としているようで、OnDeserialization
呼び出されたときに辞書が完全に初期化されることを期待していました...しかし、同じエラーが発生します!
[Serializable]
class Foo : IDeserializationCallback
{
public Dictionary<int, string> Dict { get; private set; }
public Foo()
{
Dict = new Dictionary<int, string>();
}
public void OnDeserialization(object sender)
{
Dict.Add(99, "test"); // Error here
}
}
は子オブジェクトでコードを実行するように設計されているためIDeserializationCallback
、この時点で子オブジェクトは完全に初期化されると思います。辞書を手動で呼び出すとOnDeserialize
正常に機能しますが、どういうわけか私はそれを行うことになっていないことに注意してください...
この動作は正常ですか?誰かがここで何が起こっているのか説明できますか?