秒懂C#通过Emit动态生成代码
首先需要声明一个程序集名称,
1 // specify a new assembly name
2 var assemblyName = new AssemblyName("Kitty");
从当前应用程序域获取程序集构造器,
1 // create assembly builder
2 var assemblyBuilder = AppDomain.CurrentDomain
3 .DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
有几种动态程序集构造访问限制:
- AssemblyBuilderAccess.Run; 表示程序集可被执行,但不能被保存。
- AssemblyBuilderAccess.Save; 表示程序集可被保存,但不能被执行。
- AssemblyBuilderAccess.RunAndSave; 表示程序集可被保存并能被执行。
- AssemblyBuilderAccess.ReflectionOnly; 表示程序集只能用于反射上下文环境中,不能被执行。
- AssemblyBuilderAccess.RunAndCollect; 表示程序集可以被卸载并且内存会被回收。
在程序集中构造动态模块,
1 // create module builder
2 var moduleBuilder = assemblyBuilder.DefineDynamicModule("KittyModule", "Kitty.exe");
模块即是代码的集合,一个程序集中可以有多个模块。并且理论上讲,每个模块可以使用不同的编程语言实现,例如C#/VB。
构造一个类型构造器,
1 // create type builder for a class
2 var typeBuilder = moduleBuilder.DefineType("HelloKittyClass", TypeAttributes.Public);
通过类型构造器定义一个方法,获取方法构造器,获得方法构造器的IL生成器,通过编写IL代码来定义方法功能。

1 // create method builder
2 var methodBuilder = typeBuilder.DefineMethod(
3 "SayHelloMethod",
4 MethodAttributes.Public | MethodAttributes.Static,
5 null,
6 null);
7
8 // then get the method il generator
9 var il = methodBuilder.GetILGenerator();
10
11 // then create the method function
12 il.Emit(OpCodes.Ldstr, "Hello, Kitty!");
13 il.Emit(OpCodes.Call,
14 typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
15 il.Emit(OpCodes.Call, typeof(Console).GetMethod("ReadLine"));
16 il.Emit(OpCodes.Pop); // we just read something here, throw it.
17 il.Emit(OpCodes.Ret);

创建类型,
1 // then create the whole class type
2 var helloKittyClassType = typeBuilder.CreateType();
如果当前程序集是可运行的,则设置一个程序入口,
1 // set entry point for this assembly
2 assemblyBuilder.SetEntryPoint(helloKittyClassType.GetMethod("SayHelloMethod"));
将动态生成的程序集保存成磁盘文件,
1 // save assembly
2 assemblyBuilder.Save("Kitty.exe");
此时,通过反编译工具,将Kitty.exe反编译成代码,

1 using System;
2
3 public class HelloKittyClass
4 {
5 public static void SayHelloMethod()
6 {
7 Console.WriteLine("Hello, Kitty!");
8 Console.ReadLine();
9 }
10 }

运行结果,
完整代码

1 using System;
2 using System.Reflection;
3 using System.Reflection.Emit;
4
5 namespace EmitIntroduction
6 {
7 class Program
8 {
9 static void Main(string[] args)
10 {
11 // specify a new assembly name
12 var assemblyName = new AssemblyName("Kitty");
13
14 // create assembly builder
15 var assemblyBuilder = AppDomain.CurrentDomain
16 .DefineDynamicAssembly(assemblyName,
17 AssemblyBuilderAccess.RunAndSave);
18
19 // create module builder
20 var moduleBuilder =
21 assemblyBuilder.DefineDynamicModule(
22 "KittyModule", "Kitty.exe");
23
24 // create type builder for a class
25 var typeBuilder =
26 moduleBuilder.DefineType(
27 "HelloKittyClass", TypeAttributes.Public);
28
29 // create method builder
30 var methodBuilder = typeBuilder.DefineMethod(
31 "SayHelloMethod",
32 MethodAttributes.Public | MethodAttributes.Static,
33 null,
34 null);
35
36 // then get the method il generator
37 var il = methodBuilder.GetILGenerator();
38
39 // then create the method function
40 il.Emit(OpCodes.Ldstr, "Hello, Kitty!");
41 il.Emit(OpCodes.Call,
42 typeof(Console).GetMethod(
43 "WriteLine", new Type[] { typeof(string) }));
44 il.Emit(OpCodes.Call,
45 typeof(Console).GetMethod("ReadLine"));
46 il.Emit(OpCodes.Pop); // we just read something here, throw it.
47 il.Emit(OpCodes.Ret);
48
49 // then create the whole class type
50 var helloKittyClassType = typeBuilder.CreateType();
51
52 // set entry point for this assembly
53 assemblyBuilder.SetEntryPoint(
54 helloKittyClassType.GetMethod("SayHelloMethod"));
55
56 // save assembly
57 assemblyBuilder.Save("Kitty.exe");
58
59 Console.WriteLine(
60 "Hi, Dennis, a Kitty assembly has been generated for you.");
61 Console.ReadLine();
62 }
63 }
64 }

秒懂C#通过Emit动态生成代码的更多相关文章
- 秒懂C#通过Emit动态生成代码 C#使用Emit构造拦截器动态代理类
秒懂C#通过Emit动态生成代码 首先需要声明一个程序集名称, 1 // specify a new assembly name 2 var assemblyName = new Assembly ...
- Emit动态生成代码
Emit动态生成代码 引用:秒懂C#通过Emit动态生成代码 首先需要声明一个程序集名称, // specify a new assembly name var assemblyName = new ...
- Emit动态生成代理类用于监控对象的字段修改
利用Emit动态生成代理对象监控对象哪些字段被修改,被修改为什么值 被Register的对象要监控的值必须是Virtual虚类型 必须使用CreateInstance创建对象 必须使用DynamicP ...
- CodeTypeDeclaration,CodeMemberProperty动态生成代码
由于是CodeDom些列,所以先介绍几个CodeDom表达式: :CodeConditionStatement:判断语句即是if(condition){} else{},看最全的那个构造函数: pub ...
- Emit 自动生成IL代码,注入代码
Spring 框架中的注入代码,以及自动生成对接口的实现,则根据il代码注入 Emit学习(1)-Emit概览 一.Emit概述 Emit,可以称为发出或者产生.在Framework中,与Emit相关 ...
- Android 动态生成布局 (多层嵌套)
Android 除了能够载入xml文件,显示布局外,也能够代码生成布局,并通过setContentView(View view)方法显示布局.单独的一层布局,如一个主布局加一个控件(如Button\i ...
- C# Emit动态代理生成一个实体对象
/// <summary> /// 使用Emit动态代理收集实体信息 /// </summary> /// <typeparam name="T"&g ...
- 动态生成一个设定好特殊样式的Tlabel,快速生成代码
动态生成一个设定好特殊样式的Tlabel,快速生成代码: 1.自己先在可视化界面设定一个Label,像这样: 2.选择label,快捷键ctrl+C 复制,粘贴带代码编辑器去,会生成一段这样的窗体代码 ...
- 在后台代码中动态生成pivot项并设置EventTrigger和Action的绑定
最近在做今日头条WP的过程中,遇到需要动态生成Pivot项的问题.第一个版本是把几个频道写死在xaml里了,事件绑定也写在xaml里,每个频道绑定一个ObservableCollection<A ...
随机推荐
- python 中的exec
x = 10 expr = """ z = 30 sum = x + y + z print(sum) """ def func(): y ...
- 设计模式C++学习笔记之十一(Bridge桥梁模式)
桥梁模式,将抽象部分与它的实现部分分离,使它们都可以独立地变化.实现分离的办法就是增加一个类, 11.1.解释 main(),客户 IProduct,产品接口 CHouse,房子 CIPod,ip ...
- 题解-POI2014 FAR-FarmCraft
Problem bzoj权限题,洛谷上可提交 洛谷上的奇葩翻译不要看,很多条件缺漏 题意简述:给定一棵树,每条边权为1,给定所有点点权,每条边仅能走两次,求以一定顺序遍历整棵树后,使所有点中的到达时间 ...
- MySQL高可用方案-PXC(Percona XtraDB Cluster)环境部署详解
MySQL高可用方案-PXC(Percona XtraDB Cluster)环境部署详解 Percona XtraDB Cluster简称PXC.Percona Xtradb Cluster的实现是在 ...
- Ex 7_21 在一个流网络中,一条边被称为是临界的...第十三次作业
如果原图中的一条边e(u,v)是临界边,则在求解最大流的过程中这条边的流量将会被占满,即在残量图中只存在反向边e(v,u),不存在正向边e(u,v).但是残量图中并不是所有的只存在反向边的顶点对之间的 ...
- Struts2中类数据封装的方式
第一种方式:属性驱动提供对应属性的set方法进行数据的封装.表单的哪些属性需要封装数据,那么在对应的Action类中提供该属性的set方法即可.表单中的数据提交,最终找到Action类中的setXxx ...
- 配置 Confluence 6 安全的最佳实践
让一个系统能够变得更加坚固的最好办法是将系统独立出来.请参考你公司的安全管理策略和相关人员来找到你公司应该采用何种安全策略.这里有很多事情需要我们考虑,例如考虑如何安装我们的操作系统,应用服务器,数据 ...
- Confluence 6 数据库表-内容(Content)
这部分的内容描述了有关 Confluence 存储内容所使用的表格.内容是用户在 Confluence 存储和分享的信息. attachmentdata 附件文件的二进制数据.当 Confluence ...
- input,select默认颜色修改
input::-webkit-input-placeholder{color: #7f7f7f;} select{color: #7f7f7f} option{color: #7f7f7f;}
- 【python】多进程与mongo
参考:http://api.mongodb.com/python/current/faq.html#using-pymongo-with-multiprocessing 如果使用了多进程,则必须在子进 ...