配色: 字号:
C#通过Emit动态生成代码
2016-09-14 | 阅:  转:  |  分享 
  
C#通过Emit动态生成代码
首先需要声明一个程序集名称,

1//specifyanewassemblyname
2varassemblyName=newAssemblyName("Kitty");
从当前应用程序域获取程序集构造器,

1//createassemblybuilder
2varassemblyBuilder=AppDomain.CurrentDomain
3.DefineDynamicAssembly(assemblyName,AssemblyBuilderAccess.RunAndSave);
有几种动态程序集构造访问限制:

AssemblyBuilderAccess.Run;表示程序集可被执行,但不能被保存。
AssemblyBuilderAccess.Save;表示程序集可被保存,但不能被执行。
AssemblyBuilderAccess.RunAndSave;表示程序集可被保存并能被执行。
AssemblyBuilderAccess.ReflectionOnly;表示程序集只能用于反射上下文环境中,不能被执行。
AssemblyBuilderAccess.RunAndCollect;表示程序集可以被卸载并且内存会被回收。
在程序集中构造动态模块,

1//createmodulebuilder
2varmoduleBuilder=assemblyBuilder.DefineDynamicModule("KittyModule","Kitty.exe");
模块即是代码的集合,一个程序集中可以有多个模块。并且理论上讲,每个模块可以使用不同的编程语言实现,例如C#/VB。
构造一个类型构造器,

1//createtypebuilderforaclass
2vartypeBuilder=moduleBuilder.DefineType("HelloKittyClass",TypeAttributes.Public);
通过类型构造器定义一个方法,获取方法构造器,获得方法构造器的IL生成器,通过编写IL代码来定义方法功能。

复制代码
1//createmethodbuilder
2varmethodBuilder=typeBuilder.DefineMethod(
3"SayHelloMethod",
4MethodAttributes.Public|MethodAttributes.Static,
5null,
6null);
7
8//thengetthemethodilgenerator
9varil=methodBuilder.GetILGenerator();
10
11//thencreatethemethodfunction
12il.Emit(OpCodes.Ldstr,"Hello,Kitty!");
13il.Emit(OpCodes.Call,
14typeof(Console).GetMethod("WriteLine",newType[]{typeof(string)}));
15il.Emit(OpCodes.Call,typeof(Console).GetMethod("ReadLine"));
16il.Emit(OpCodes.Pop);//wejustreadsomethinghere,throwit.
17il.Emit(OpCodes.Ret);
复制代码
创建类型,

1//thencreatethewholeclasstype
2varhelloKittyClassType=typeBuilder.CreateType();
如果当前程序集是可运行的,则设置一个程序入口,

1//setentrypointforthisassembly
2assemblyBuilder.SetEntryPoint(helloKittyClassType.GetMethod("SayHelloMethod"));
将动态生成的程序集保存成磁盘文件,

1//saveassembly
2assemblyBuilder.Save("Kitty.exe");
此时,通过反编译工具,将Kitty.exe反编译成代码,

复制代码
1usingSystem;
2
3publicclassHelloKittyClass
4{
5publicstaticvoidSayHelloMethod()
6{
7Console.WriteLine("Hello,Kitty!");
8Console.ReadLine();
9}
10}
复制代码
运行结果,


完整代码
复制代码
1usingSystem;
2usingSystem.Reflection;
3usingSystem.Reflection.Emit;
4
5namespaceEmitIntroduction
6{
7classProgram
8{
9staticvoidMain(string[]args)
10{
11//specifyanewassemblyname
12varassemblyName=newAssemblyName("Kitty");
13
14//createassemblybuilder
15varassemblyBuilder=AppDomain.CurrentDomain
16.DefineDynamicAssembly(assemblyName,
17AssemblyBuilderAccess.RunAndSave);
18
19//createmodulebuilder
20varmoduleBuilder=
21assemblyBuilder.DefineDynamicModule(
22"KittyModule","Kitty.exe");
23
24//createtypebuilderforaclass
25vartypeBuilder=
26moduleBuilder.DefineType(
27"HelloKittyClass",TypeAttributes.Public);
28
29//createmethodbuilder
30varmethodBuilder=typeBuilder.DefineMethod(
31"SayHelloMethod",
32MethodAttributes.Public|MethodAttributes.Static,
33null,
34null);
35
36//thengetthemethodilgenerator
37varil=methodBuilder.GetILGenerator();
38
39//thencreatethemethodfunction
40il.Emit(OpCodes.Ldstr,"Hello,Kitty!");
41il.Emitwww.wang027.com(OpCodes.Call,
42typeof(Console).GetMethod(
43"WriteLine",newType[]{typeof(string)}));
44il.Emit(OpCodes.Call,
45typeof(Console).GetMethod("ReadLine"));
46il.Emit(OpCodes.Pop);//wejustreadsomethinghere,throwit.
47il.Emit(OpCodes.Ret);
48
49//thencreatethewholeclasstype
50varhelloKittyClassType=typeBuilder.CreateType();
51
52//setentrypointforthisassembly
53assemblyBuilder.SetEntryPoint(
54helloKittyClassType.GetMethod("SayHelloMethod"));
55
56//saveassembly
57assemblyBuilder.Save("Kitty.exe");
58
59Console.WriteLine(
60"Hi,Dennis,aKittyassemblyhasbeengeneratedforyou.");
61Console.ReadLine();
62}
63}
64}
复制代码
献花(0)
+1
(本文系thedust79首藏)