BinaryFormatter#Deserialize(4)

先日のデシリアライズ時のトラブル

今回のケースでは、IPCを行う二つのアプリケーションが、同一のアセンブリに属する同一の型を使って情報をやり取りするわけで、アセンブリやクラスのバージョンは変わらないはずだ。それでもデシリアライズが上手くいかないのは、.NETの場合、同一のアセンブリ、同一の型であっても、違う場所に配置されているアセンブリや型は"同一"とみなされないからだろう。(ここは推測の域を出ない。どなたか、この部分に関しての確信が書いてある文献やサイト、書籍があれば、是非教えて頂だけないだろうか)

に関して新たな情報を見つけたんで、忘れないうちにメモ

Run-time Serialization (MSDN Magazine April 2002)

この記事の日本語訳「マイクロソフトテクノロジー エンサイクロペディア −Best of MSDN Magazine 2000〜2003年 DVD-ROM版− 」として発売(※)されているDVD中に掲載されている記事、「.NETランタイムのシリアル機能」中に

ところがこのストリームを逆シリアル化する場合には,フォーマッタはLoadFromメソッドではなく,アセンブリのLoadメソッドかLoadWithPartialNameメソッドを呼び出してアセンブリをロードしようとします。するとほとんどの場合には共通言語ランタイム(CLR)がアセンブリファイルを見つけられずに,SerializationException 例外がスローされる結果になります。これには多くの開発者が驚かされています。

と、私が遭遇した現象がしっかりと書いてありました。更に、著者が言うところの解決策ですが、残念ながら私が書いたと同様のSerializationBinderクラスを用意することではありませんでした。

シリアル化するオブジェクトの型が,Assembly.LoadFromによってロードされるアセンブリ中で定義されている場合には,シグネチャがSystem.ResolveEventHandlerデリゲートとマッチするメソッドを実装することをお勧めします。〜中略〜 このメソッドには,ロードに失敗したアセンブリのアイデンティティが渡されます。そのためこのメソッドでアセンブリのアイデンティティからアセンブリファイル名を抽出し,アセンブリが存在する既知の場所とその名前を組み合わせればパスを作成できます。そうしたらAssembly.LoadFromを呼び出してアセンブリをロードし,ResolveEventHandlerメソッドからそのアセンブリの参照を返せばいいのです。

実際に試してみてから結論を出しますが、正しい解決策は、アセンブリの解決が上手くいかない場合を想定して、ResolveEventHandlerを処理してやるのが良いみたいです。

マイクロソフトテクノロジーエンサイクロペディアDVD-ROM版によると、もうASCIIの管轄ではないとのことです。
私のような.NET後学者にとって、このシリーズは非常に貴重な文献なので、是非購入の手段を残しておいて頂きたいものです。