Hashtable.OnDeserialization
-
07-07-2019 - |
質問
Hashtableへの参照を維持し、そのHashtableをシリアライズ/デシリアライズするクラスがあります。 SerializationInfo.GetValueを呼び出した後、IDeserialization calbackの間に逆シリアル化が行われるため、Hashtableは完全に逆シリアル化されません。
Hashtable hashtable = (Hashtable) info.GetValue("hash", typeof(Hashtable));
IDeserializationコールバックも親クラスに実装しましたが、Hashtableも完全に非シリアル化されていません。逆シリアル化が内部から発生していると予想しました。
私の質問は、親クラスのOnDeserializationメソッドから明示的にHashtable.OnDeserializationを呼び出して、その時点で列挙できるようにすることは安全ですか?
public virtual void OnDeserialization(object sender)
{
hashtable.OnDeserialization(sender);
}
解決
これは本当に興味深い問題です。 Reflectorでシリアル化コードをチェックした後、参照されたクラスがIDeserializationCallbackを使用している場合、一般的に良い解決策はないと思います。
おそらく、逆シリアル化中にいくつかのコードを実行する方法として、[OnDeserializing]属性と[OnDeserialized]属性の2つの方法があることをご存知でしょう。残念ながら、両方ともIDeserializationCallback.OnDeserialization()の前に実行されます。 class2を参照するclass1がある場合、これはメソッドの実行順序です。
Class1: [OnDeserializing]
Class2: [OnDeserializing]
Class2: [OnDeserialized]
Class1: [OnDeserialized]
Class1: IDeserializationCallback.OnDeserialization
Class2: IDeserializationCallback.OnDeserialization
ご覧のとおり、[OnDeserializing]属性と[OnDeserialized]属性は一貫して機能しますが、IDeserializationCallbackメソッドは実際にはそうではありません...:(
HashtableとDictionaryのOnDeserialization実装も確認しましたが、どちらもOnDeserializationを複数回呼び出すのに安全であるようです(最初の呼び出しのみが必要な操作を実行し、後続の呼び出しは何も行いません)。
最後に、 Sean とBrianが提案しました。
他のヒント
既にグーグルで検索したことがありますが、たまたま昨日パターン。
public BoringClass(SerializationInfo info, StreamingContext context)
{
Hashtable hashtable = (Hashtable) info.GetValue("hash", typeof(Hashtable));
hashtable.OnDeserialization(this);
Console.WriteLine("Value is: " + hashtable["testItem"]);
}