Skip to content

Instantly share code, notes, and snippets.

@sunnyone
Created August 18, 2012 16:20
HelloWorld Generator
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);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment