zipファイルからのアセンブリロード
開発しているとDLLが大量に出来て邪魔くさいことがあります。機能単位でディレクトリを分けてしまえば済む話ですが、zipあたりで圧縮して実行時にその中のアセンブリを取り出せれば、ちょっとだけ良さそうな気がします。ようはJavaのjarファイルです。ということでjarもどきをこさえてみました。
using System; using System.IO; using System.Collections; using System.Reflection; using ICSharpCode.SharpZipLib.Zip; class App { [STAThread] static void Main(string args) { if (args.Length != 2) { Console.WriteLine("usage app.exe exe zip"); return; } AppDomain domain = AppDomain.CreateDomain("Main"); // zipファイルをサーチパスに加える domain.SetData("ZipPath", args[1]); domain.AssemblyResolve += new ResolveEventHandler(OnAssemblyResolve); domain.ExecuteAssembly(args[0]); } public static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) { Assembly asm = null; ZipFile zip = new ZipFile(AppDomain.CurrentDomain.GetData("ZipPath") as string); try { string files = args.Name.Split(new char {','}); ZipEntry e = zip.GetEntry(files[0] + ".dll"); byte dll = new byte [e.Size]; zip.GetInputStream(e).Read(dll, 0, dll.Length); asm = Assembly.Load(dll); } finally { zip.Close(); } return asm; } }
で、こんな感じで実行。
$ app.exe main.exe dll.zip
main.exeが参照しているアセンブリはdll.zipの中にアーカイブされています。
アセンブリの参照解決出来ない場合にはAppDomainのAssemblyResolveイベントが呼ばれ、ここで自力で参照解決するチャンスがあります。AssemblyResolveイベントの戻り値はAssemblyとなっているので、何らかの方法でAssemblyオブジェクトが生成出来れば良いはずです。そこで例ではzipファイルから該当DLLのイメージをbyte[]に読み込んでAssemblyを生成しています。アセンブリ名を持ってくるのにSplitでぶった切って.DLLをくっつけているのはイマイチですが、使えそうな気がします。