3

バイナリシリアル化の奇妙な動作に気づきました。クラスの辞書を逆シリアル化し、すぐに何かを追加しようとすると、完全に初期化されていないため、エラーが発生します。

[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正常に機能しますが、どういうわけか私はそれを行うことになっていないことに注意してください...

この動作は正常ですか?誰かがここで何が起こっているのか説明できますか?

4

2 に答える 2

1

Dict.OnDeserialization(sender)逆シリアル化ハンドラーに追加すると、すべてがうまくいきます。

したがって、これは機能します:

    [Serializable]
    class Foo : IDeserializationCallback
    {
        public Dictionary<int, string> Dict { get; private set; }

        public Foo()
        {
            Dict = new Dictionary<int, string>();
        }

        public void OnDeserialization(object sender)
        {
            // The dictionary is initialized with values in next line
            Dict.OnDeserialization(sender);
            Dict.Add(99, "test");
        }
    }
于 2011-12-11T17:13:03.770 に答える
0

OnDeserialization ハンドラで Dictionary<> をインスタンス化する必要があります

public void OnDeserialization(object sender)
{
    Dict = new Dictionary<int, string>();
    Dict.Add(99, "test"); // Error here
}
于 2011-12-09T15:50:42.150 に答える