使用Reflection.Emit运行时生成代码

此文来之于<<Generating Code at Run Time With Reflection.Emit>>,不过没有完全按照作文翻译,记录了一些要点,方便自己记忆。

  CLR里包含一个Reflection.Emit的命名空间,该空间下的类帮助大家在运行时创建程序集、类和函数。那如何使用这些类来动态地创建代码呢?先来解释下.net代码的上下文环境。程序集(Assembly)、模块(Module)、类型(Type)和方法(Method)。.net运行时环境组织结构是代码隶属于方法,方法隶属于类型,类型隶属于模块,模块隶属于程序集。可执行文件、临时程序集(存于内存中)都需要满足这个组织结构。因此使用 Reflection.Emit 生成代码的步骤如下:

• 定义动态程序集。(Reflection.Emit不允许在原有的Assembly上添加代码)
• 在该程序集中创建一个模块。
• 在该模块中定义一个类型(以便从适当的代码基类和该类型的方法 interface(s):Create 派生类型)。

• 在该类型上定义一个方法,获取每个方法的 ILGenerator,在适当的时候发出 IL 操作码,以及保持该类型。
• 可以选择保存该程序集以供将来使用。
  下面给出一个简单的例子来说明如何使用Reflection.Emit来构造类。 

  准备使用Reflection.Emit来创建下面的类:

代码
div>public class class1
{
public static int Main(string[] strArr)
{
Console.WriteLine(
"hello world");
Console.ReadLine();
return 0;
}
}

代码如下:

 

代码
 public class GeneratorDemo
{
public static void Generator()
{
// 获取当前应用程序域
AppDomain currDomain = AppDomain.CurrentDomain;
// 程序集名称
AssemblyName asmName = new AssemblyName("DynamicAssembly");
// 定义动态程序集,注意AssemblyBuilderAccess参数的选择
AssemblyBuilder asmBuilder = currDomain.DefineDynamicAssembly(asmName,
AssemblyBuilderAccess.Save);
// 定义模块,其中Hello.exe是Module保存到磁盘的名称,Module是代码和资源的存储地方,
// Assembly是Module的元数据存储地方,一般情况Module和Assembly保存到同一个文件里,
// 在asmBuilder.Save()指定相同的名称即可,不过这不是必须的。
ModuleBuilder moudleBuilder = asmBuilder.DefineDynamicModule("DynamicModule", "Hello.exe");
// 定义类
TypeBuilder typeBuilder = moudleBuilder.DefineType("Demo.Class1", TypeAttributes.Class
| TypeAttributes.Public);
// 定义方法
MethodBuilder methodBuilder = typeBuilder.DefineMethod("Main", MethodAttributes.Static
| MethodAttributes.Public,
CallingConventions.Standard,
typeof(int), new Type[] { typeof(string[]) });
// 获取IL生成器
ILGenerator generator = methodBuilder.GetILGenerator();
// Console.WriteLine("hello world");
generator.EmitWriteLine("hello world");
// Console.ReadLine();
MethodInfo methodInfo = typeof(Console).GetMethod("ReadLine", new Type[] { });
generator.Emit(OpCodes.Call, methodInfo);
generator.Emit(OpCodes.Pop);
// return 0;
generator.Emit(OpCodes.Ldc_I4_0);
generator.Emit(OpCodes.Ret);

typeBuilder.CreateType();
// 设置程序入口点
asmBuilder.SetEntryPoint(methodBuilder, PEFileKinds.ConsoleApplication);

asmBuilder.Save(
"Hello.exe");
}
}

 

 

上面是一个简单的例子,关于IL生成,下次再写

posted @ 2010-04-19 15:30  hs0014  阅读(320)  评论(0编辑  收藏  举报