うならぼ

どうも。

Mono.Cecilだけでアセンブリをマージ

VisualStudio起動するのが面倒でLINQPadばかり使っています。小物ツールもLINQPadで書いてQueriesの中に放り込んでますし、MyExtensionsも1000行を超えています。分割したい。

こうなってくるとLINQPadからexeやdllを書き出したくなるわけです。実際のところ、LINQPadは実行時にdllを生成しているので、ちょいちょいとメタデータをいじってやればexeになります。それもMyExtensionsに入れたんですが、それはまた別の日に書くとして。

exeにしたのなら、MyExtensionsやNuGetのアセンブリも埋め込んでしまいたいところです。

アセンブリの埋め込みというとMS謹製のILMergeや、それのMono版であるILRepackが定番かと思いますが、Mono.Cecilだけでもうちょっと手軽にできないものでしょうか。

というのがこちら。あまり深く動作確認はしていません。

gist.github.com

TypeDefやTypeRefをモジュール間で移動してるだけですね。

こういう操作では各メタデータ間の参照や整合性を保つのが面倒なものですが、Mono.Cecilはこれらの関係をオブジェクトの参照関係に置き換えてしまい、アセンブリを書き出すときに再構築してくれるので楽ちんです。

もっとも、メタデータAを参照しているところを全てメタデータBに張り替えたいと思っても、あるデータの参照元を逆引きすることはできませんし、読み取り専用だったりするとあれなんですが。実際上のコードでもいくつか強引に書き換えています。本来ならば埋め込まれたモジュールへの参照(ModuleRef)は自分のModuleDefに置き換えるべきですが、面倒なので自分自身を指すMethodRefに書き換えています。

ちなみに冒頭で紹介したILRepackもMono.Cecilを使っていますが、あちらはもっと真面目に移植しているようです。