using System; using System.Reflection; using System.Reflection.Emit; using System.Linq; using System.Threading; namespace HelloWorld1 { class Program { static void Main(string[] args) { if (args.Length != 1) { System.Console.Error.WriteLine("usage: HelloWorld1 filename.exe"); System.Environment.Exit(1); } string exeName = args[0]; // AssemblyBuilder#save(path)がディレクトリまたぎを受け付けないので拒否 if (System.IO.Path.GetDirectoryName(exeName).Length > 0) { System.Console.Error.WriteLine("Specifing path is not supported."); System.Environment.Exit(1); } // アプリケーションドメインの取得とアセンブリ・モジュールの作成 AppDomain appDomain = Thread.GetDomain(); AssemblyName assemblyName = new AssemblyName() { Name = exeName }; AssemblyBuilder assemblyBuilder = appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("HelloWorld", exeName, true); // クラスの作成 TypeBuilder helloClassBuilder = moduleBuilder.DefineType("Hello", TypeAttributes.Class); ConstructorBuilder ctorBuilder = helloClassBuilder.DefineDefaultConstructor(MethodAttributes.Public); // インスタンスメソッドvoid Say(string value)の作成 MethodBuilder sayMethodBuilder = helloClassBuilder.DefineMethod("Say", MethodAttributes.Public, typeof(void), new Type[] { typeof(string) }); ILGenerator ilSay = sayMethodBuilder.GetILGenerator(); // System.Console.WriteLine()にSayの第一引数を渡してコール ilSay.Emit(OpCodes.Ldarg_1); ilSay.EmitCall(OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new Type[] { typeof(String) }), null); // Sayを抜ける ilSay.Emit(OpCodes.Ret); // エントリポイントとなる静的メソッドの作成 MethodInfo thisMainMethod = System.Reflection.Assembly.GetExecutingAssembly().EntryPoint; MethodBuilder mainMethodBuilder = helloClassBuilder.DefineMethod( thisMainMethod.Name, thisMainMethod.Attributes, thisMainMethod.ReturnType, (from p in thisMainMethod.GetParameters() select p.ParameterType).ToArray<Type>()); ILGenerator ilMain = mainMethodBuilder.GetILGenerator(); // ローカル変数を宣言してメッセージを格納 LocalBuilder msgLocal = ilMain.DeclareLocal(typeof(string)); ilMain.Emit(OpCodes.Ldstr, "Hello, World"); ilMain.Emit(OpCodes.Stloc, msgLocal); // ローカル変数を宣言してHelloオブジェクトを生成・格納 LocalBuilder helloLocal = ilMain.DeclareLocal(helloClassBuilder); ilMain.Emit(OpCodes.Newobj, ctorBuilder); ilMain.Emit(OpCodes.Stloc, helloLocal); // 作成したオブジェクトに対して、Sayメソッドを実行 ilMain.Emit(OpCodes.Ldloc, helloLocal); ilMain.Emit(OpCodes.Ldloc, msgLocal); ilMain.EmitCall(OpCodes.Call, sayMethodBuilder, null); // メイン終了 ilMain.Emit(OpCodes.Ret); // Helloクラスの作成 helloClassBuilder.CreateType(); // エントリポイントの設定 assemblyBuilder.SetEntryPoint(mainMethodBuilder); // 保存 assemblyBuilder.Save(exeName); } } }