XmlSerializer の実行時コード生成を止める方法

id:siokoshou:20071103:p2 の続き。

List を使ってたのをやめて配列にしてみたけど、やっぱりコードの自動生成&コンパイルは止まりません。しょうがないので、もう一度 WinDbg で止めて生成したコードを眺めてみると、ArrayOfHoge という、ユーザ定義 Hoge クラスの配列を扱うコードが生成されてました。id:shiba-yan さんに教えてもらった sgen /k を使って、/a でアセンブリのすべての型への XmlSerializer コードを出してみると、Hoge[] が含まれていません。そりゃそうだよね、全部の型に対して配列の分も用意してたら大変なことになるし。

MS 製 sgen の問題

それじゃあ、sgen に Hoge[] を出してもらおうとしたら…。/t オプションで型を指定できるんですが、一つしか認識してくれないようです…。2つの型のコードを出したいんです!それも /a では出てこないやつも含めて。吐き出されたコードを手作業でマージする手もあるけど、ここはなんとか自動化したいところ。
ぐぐってみると、同じ問題にぶつかってる人が既にいました。投稿者さんは MS から sgenplus という別のツールをもらったようですが、mono の sgen なら複数の型に対応してるよって情報も。試しに mono の sgen を使ってみました。
http://anonsvn.mono-project.com/viewcvs/trunk/mcs/tools/sgen/

mono の sgen の問題とその修正

mono の sgen はそのまま MS.NET 環境で動きました。/t が複数あればきちんと複数の型に対するコードが出てきました!が、こちらはこちらで配列に対応してませんでした…。/t:Hoge[] だとコードが出てきません。でも、試しにちょっとコードをいじってみたら、簡単に直ってしまいました。やっぱコードが公開されてることは重要ですね。助かります。sgen 自体はたいしたことはしてなくて、型をパラメータとして渡してやればあとは .NET の内部でゴソゴソしてくれるようです。

これで生成した Fuga.XmlSerializers.dll を実行ファイルと同じディレクトリに置いて、Filemon で見ながら実行してみると、遂にコード生成なしで動きました!めでたし!長かった。

その後、mono の sgen を id:atsushieno さんに協力していただいて登録してもらえました。ありがとうございます!オリジナルの sgen が実は /t なしだと MS.NET 環境で例外を出すという別の問題にぶつかったりもしたんですが、そちらもついでに直しました。ものすごいちっちゃい修正ですが(^^;

というわけで、XmlSerializer のコード自動生成でデッドロックや遅さにお困りの方は mono の sgen を試してみてください。デッドロック回避の WinXP のパッチも出てますが、ユーザに入れてという訳にはいかない場合にどうぞ。
自動生成してるかどうかは Filemon で確認できます。Filter の Exclude に普段から I/O してるプロセス名を登録しまくってマスクして、検索で「.cs」を探すと楽です。F3 で次の検索、Shift+F3 で逆方向へ検索もできます。

結局、VisualStudio の「シリアル化アセンブリの生成」はよくわからないままでしたw