Emit动态生成代码
Emit动态生成代码
首先需要声明一个程序集名称,
// specify a new assembly name
var assemblyName = new AssemblyName("Kitty");
从当前应用程序域获取程序集构造器,
// create assembly builder
var assemblyBuilder=AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
有几种动态程序集构造访问限制:
- AssemblyBuilderAccess.Run; 表示程序集可被执行,但不能被保存。
- AssemblyBuilderAccess.Save; 表示程序集可被保存,但不能被执行。
- AssemblyBuilderAccess.RunAndSave; 表示程序集可被保存并能被执行。
- AssemblyBuilderAccess.ReflectionOnly; 表示程序集只能用于反射上下文环境中,不能被执行。
- AssemblyBuilderAccess.RunAndCollect; 表示程序集可以被卸载并且内存会被回收。
在程序集中构造动态模块,
// create module builder
var moduleBuilder = assemblyBuilder.DefineDynamicModule("KittyModule", "Kitty.exe");
模块即是代码的集合,一个程序集中可以有多个模块。并且理论上讲,每个模块可以使用不同的编程语言实现,例如C#/VB。
构造一个类型构造器,
// create type builder for a class
var typeBuilder = moduleBuilder.DefineType("HelloKittyClass", TypeAttributes.Public);
通过类型构造器定义一个方法,获取方法构造器,获得方法构造器的IL生成器,通过编写IL代码来定义方法功能。
// create method builder
var methodBuilder = typeBuilder.DefineMethod(
"SayHelloMethod",
MethodAttributes.Public | MethodAttributes.Static,
null,
null); // then get the method il generator
var il = methodBuilder.GetILGenerator(); // then create the method function
il.Emit(OpCodes.Ldstr, "Hello, Kitty!");
il.Emit(OpCodes.Call,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
il.Emit(OpCodes.Call, typeof(Console).GetMethod("ReadLine"));
il.Emit(OpCodes.Pop); // we just read something here, throw it.
il.Emit(OpCodes.Ret);
创建类型,
// then create the whole class type
var helloKittyClassType = typeBuilder.CreateType();
如果当前程序集是可运行的,则设置一个程序入口,
// set entry point for this assembly
assemblyBuilder.SetEntryPoint(helloKittyClassType.GetMethod("SayHelloMethod"));
将动态生成的程序集保存成磁盘文件,
// save assembly
assemblyBuilder.Save("Kitty.exe");
此时,通过反编译工具,将Kitty.exe反编译成代码,
using System; public class HelloKittyClass
{
public static void SayHelloMethod()
{
Console.WriteLine("Hello, Kitty!");
Console.ReadLine();
}
}
运行结果,
完整代码
using System;
using System.Reflection;
using System.Reflection.Emit; namespace EmitIntroduction
{
class Program
{
static void Main(string[] args)
{
// specify a new assembly name
var assemblyName = new AssemblyName("Kitty"); // create assembly builder
var assemblyBuilder = AppDomain.CurrentDomain
.DefineDynamicAssembly(assemblyName,
AssemblyBuilderAccess.RunAndSave); // create module builder
var moduleBuilder =
assemblyBuilder.DefineDynamicModule(
"KittyModule", "Kitty.exe"); // create type builder for a class
var typeBuilder =
moduleBuilder.DefineType(
"HelloKittyClass", TypeAttributes.Public); // create method builder
var methodBuilder = typeBuilder.DefineMethod(
"SayHelloMethod",
MethodAttributes.Public | MethodAttributes.Static,
null,
null); // then get the method il generator
var il = methodBuilder.GetILGenerator(); // then create the method function
il.Emit(OpCodes.Ldstr, "Hello, Kitty!");
il.Emit(OpCodes.Call,
typeof(Console).GetMethod(
"WriteLine", new Type[] { typeof(string) }));
il.Emit(OpCodes.Call,
typeof(Console).GetMethod("ReadLine"));
il.Emit(OpCodes.Pop); // we just read something here, throw it.
il.Emit(OpCodes.Ret); // then create the whole class type
var helloKittyClassType = typeBuilder.CreateType(); // set entry point for this assembly
assemblyBuilder.SetEntryPoint(
helloKittyClassType.GetMethod("SayHelloMethod")); // save assembly
assemblyBuilder.Save("Kitty.exe"); Console.WriteLine(
"Hi, Dennis, a Kitty assembly has been generated for you.");
Console.ReadLine();
}
}
}
Emit动态生成代码的更多相关文章
- 秒懂C#通过Emit动态生成代码 C#使用Emit构造拦截器动态代理类
秒懂C#通过Emit动态生成代码 首先需要声明一个程序集名称, 1 // specify a new assembly name 2 var assemblyName = new Assembly ...
- 秒懂C#通过Emit动态生成代码
首先需要声明一个程序集名称, 1 // specify a new assembly name 2 var assemblyName = new AssemblyName("Kitty&qu ...
- 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 ...
随机推荐
- 关于SQL Server 2008添加用户映射问题 解决办法
同事一直需要用触发器 但是之前的数据库没有dbo映射 无法添加 查阅了很多资料 不适合自己的问题 所以自己动手丰衣足食 特留下笔记 希望能给遇到相同问题的朋友一个解决的思路
- 无线安全专题_破解篇02--kali破解pin码
最近项目有点紧,所以本应该上周发的文章,拖到了本周三,在此说声抱歉.无线安全专题,我打算系统地写六个部分,分别为破解篇,攻击篇,欺骗篇,路由篇,移动篇和蓝牙篇,当然在发布的过程中,可能还会掺杂着发布f ...
- solr与.net系列课程(二)solr的配置文件及其含义
solr与.net系列课程(二)solr的配置文件及其含义 本节内容还是不会涉及到.net与数据库的内容,但是不要着急,这都是学时solr必学要掌握的东西,solr可不是像其他的dll文件一样,只需 ...
- Eclipse配置详解(包括智能提示设置、智能提示插件修改,修改空格自动上屏、JDK配置、各种快捷键列表……)
Eclipse编辑器基本设置 1.添加行号 在边缘处右键 2.改字体 字体的一般配置 3.去掉拼写错误检查 4.Java代码风格 代码格式化 Ctrl + Shift + F 之后点击右边的New按钮 ...
- 使用Js脚本 修改控制IE的注册表相关设置(activex等)
使用Js脚本 修改控制IE的注册表相关设置(activex等) 分类: PHP2012-12-05 18:51 2035人阅读 评论(2) 收藏 举报 脚本写法: <SCRIPT LANGUAG ...
- 那些年我们一起追过的Linux命令
1. cd - 作用:返回上次的目录,类似于Windows的后退功能: 2. man ascii 作用:打印出八进制.十六进制和十进制的ASCII码表:(再也不用Google ASCII表啦) 3. ...
- Neo4j:Data Model Transformation:From Relation To Graph
Here are some tips that help you with the transformation: Each entity table is represented by a labe ...
- 使用Jekyll官方的ReadMore摘要功能
今天才发现,Jekyll官方就支持ReadMore摘要功能,记录一下. 我之前的方法,在index.html中 {{ post.content ||split:'<!-- more --> ...
- textarea内部换行实现
当在使用textarea的时候,有一次需求,需要做到自定义换行,而不是通过textarea定宽来自动换行,其实在html中可以直接通过<br/>来换行,同时也想到用\n来实现换行,其结果是 ...
- .NET读取Office文件内容(word、excel、ppt)
引用命名空间 using Microsoft.Office.Core; using Word = Microsoft.Office.Interop.Word; using Excel = Micros ...