MSIL实用指南-Action的生成和调用
MSIL实用指南-Action的生成和调用
System.Action用于封装一个没有参数没有返回值的方法。这里生成需要Ldftn指令。
下面讲解怎生成如下的程序。
class ActionTest
{
public static void RunAction(Action act)
{
act();
} public static void TestRunAction()
{
Action act = () => { Console.WriteLine("Test Action"); };
RunAction(act);
}
}
一.Action的调用
Action有方法Invoke,只要加载对象,调用Invoke方法就可以了。
实例代码:
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Callvirt, typeof(Action).GetMethod("Invoke", new Type[] { }));
二、生成Lamda表示式
这里的Lamda表示式即一个匿名方法,它只有一条语句。
所以这样生成:
lambdaMethod = typeBuilder.DefineMethod("<LambdaMethod>",
MethodAttributes.Private| MethodAttributes.Static,
typeof(void), new Type[] { });
ILGenerator ilGenerator = lambdaMethod.GetILGenerator();
ilGenerator.EmitWriteLine("Test Action");
ilGenerator.Emit(OpCodes.Ret);
三、生成Action实例
Action是委托,它需要使用Ldftn和Newobj指令生成实例
实例代码
ilGenerator.Emit(OpCodes.Ldnull);//静态方法加载null,实例方法加载arg_0
ilGenerator.Emit(OpCodes.Ldftn, lambdaMethod);
ilGenerator.Emit(OpCodes.Newobj, typeof(Action).GetConstructors()[]);
完整程序:
using System;
using System.Reflection;
using System.Reflection.Emit; namespace LX1_ILDemo
{
class Demo28_Action
{
static string binaryName = "Demo28_Action.exe";
static string namespaceName = "LX1_ILDemo";
static string typeName = "Demo28"; static AssemblyBuilder assemblyBuilder;
static ModuleBuilder moduleBuilder;
static TypeBuilder typeBuilder;
static MethodBuilder mainMethod;
static MethodBuilder runActionMethod;
static MethodBuilder lambdaMethod; static void Emit_TestMethod()
{
runActionMethod = typeBuilder.DefineMethod("RunAction", MethodAttributes.Public
| MethodAttributes.Static, typeof(void), new Type[] { typeof(Action) });
ILGenerator ilGenerator = runActionMethod.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Callvirt, typeof(Action).GetMethod("Invoke", new Type[] { }));
ilGenerator.Emit(OpCodes.Ret);
} public static void Generate()
{
InitAssembly();
typeBuilder = moduleBuilder.DefineType(namespaceName + "." + typeName, TypeAttributes.Public); Emit_TestMethod();
GenerateMain(); assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication);
SaveAssembly();
Console.WriteLine("生成成功");
} static void GenerateLambda()
{
lambdaMethod = typeBuilder.DefineMethod("<LambdaMethod>",
MethodAttributes.Private| MethodAttributes.Static,
typeof(void), new Type[] { });
ILGenerator ilGenerator = lambdaMethod.GetILGenerator();
ilGenerator.EmitWriteLine("Test Action");
ilGenerator.Emit(OpCodes.Ret);
} static void GenerateMain()
{
mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public
| MethodAttributes.Static, typeof(void), new Type[] { });
ILGenerator ilGenerator = mainMethod.GetILGenerator(); LocalBuilder localBuilderv1 = ilGenerator.DeclareLocal(typeof(Action)); GenerateLambda();
ilGenerator.Emit(OpCodes.Ldnull);//静态方法加载null,实例方法加载arg_0
ilGenerator.Emit(OpCodes.Ldftn, lambdaMethod);
ilGenerator.Emit(OpCodes.Newobj, typeof(Action).GetConstructors()[]);
ilGenerator.Emit(OpCodes.Stloc_0); ilGenerator.Emit(OpCodes.Ldloc_0);
ilGenerator.Emit(OpCodes.Call, runActionMethod); EmitReadKey(ilGenerator); ilGenerator.Emit(OpCodes.Ret);
} static void EmitReadKey(ILGenerator ilGenerator)
{
MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { });
ilGenerator.Emit(OpCodes.Call, readKeyMethod);
ilGenerator.Emit(OpCodes.Pop);
} static void InitAssembly()
{
AssemblyName assemblyName = new AssemblyName(namespaceName);
assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, binaryName);
} static void SaveAssembly()
{
Type t = typeBuilder.CreateType(); //完成Type,这是必须的
assemblyBuilder.Save(binaryName);
}
}
}
MSIL实用指南-Action的生成和调用的更多相关文章
- MSIL实用指南-闭包的生成和调用
闭包(Closure)是词法闭包(Lexical Closure)的简称.对闭包的具体定义有很多种说法,这些说法大体可以分为两类: 一种说法认为闭包是符合一定条件的函数,比如参考资源中这样定义闭包:闭 ...
- MSIL实用指南-struct的生成和操作
struct(结构)是一种值类型,用于将一组相关的信息变量组织为一个单一的变量实体.所有的结构都继承自System.ValueType类,因此是一种值类型,也就是说,struct实例分配在线程的堆栈( ...
- MSIL实用指南-类相关生成
一.创建class用MethodBuilder的DefineType方法,可以指定父类,得到一个TypeBuilder对象. 二.实现继承接口用TypeBuilder的AddInterfaceImpl ...
- MSIL实用指南-this的生成
C#关键字是非静态方法体内部,用Ldarg_0指代this例子ilGenerator.Emit(OpCodes.Ldarg_0);
- MSIL实用指南-生成索引器
MSIL实用指南-生成索引器 索引器是一种特殊的属性,它有参数的,也有get和set方法,属性名称一般是"Item",并且方法名称一般名称是"get_Item" ...
- MSIL实用指南-生成属性
本篇讲解怎么生成属性,包括get和set方法. 第一步,生成一个字段生成字段用TypeBuilder.DefineField方法.实例代码: FieldBuilder customerNameBldr ...
- MSIL实用指南-生成构造函数
本篇讲解生成构造函数的一些知识,包括创建实例构造函数.静态构造函数.调用父类构造函数. 生成构造函数的方法生成构造函数的方法是TypeBuilder.DefineConstructor(MethodA ...
- MSIL实用指南-生成if...else...语句
if...else...语句是非常重要的选择语句,它的生成一般需要ILGenerator的DefineLabel方法和MarkLabel方法,以及Brtrue_S和Br_S指令. 一.DefineLa ...
- MSIL实用指南-生成foreach语句
foreach可以迭代数组或者一个集合对象.foreach语句格式是它的生成步骤是foreach (<成员> in <集合>) <循环体> 一.声明三个变量,loc ...
随机推荐
- File文件类
目录 File文件类 File类的构造方法 File类的创建功能 File类的重命名 File类的删除功能 File类的判断功能 File类的获取功能 文件名称过滤器 File文件类 File:文件和 ...
- Android CHM文件阅读器
CHM格式是1998年微软推出的基于HTML文件特性的帮助文件系统.以替代早先的winHelp帮助系统,它也是一种超文本标识语言.在Windows 98中把CHM类型文件称作“已编译的HTML帮助文件 ...
- Jenkins持续部署-创建差量更新包
目录 Jenkins持续部署-创建差量更新包 目录 前言 目的 详细流程 生成版本号 获取版本号 创建文件更新清单 压缩 获取上个版本的包 创建差量更新包 读取服务器Json配置 远程创建文件夹目录 ...
- 归并排序(从上到下、从下到上)——C语言
归并排序 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归 ...
- 【JDK】JDK源码分析-AbstractQueuedSynchronizer(3)
概述 前文「JDK源码分析-AbstractQueuedSynchronizer(2)」分析了 AQS 在独占模式下获取资源的流程,本文分析共享模式下的相关操作. 其实二者的操作大部分是类似的,理解了 ...
- Apache NiFi 核心概念和关键特性
本文来源于官方文档翻译 NiFi 的核心概念 NiFi 最早是美国国家安全局内部使用的工具,用来投递海量的传感器数据.后来由 apache 基金会开源.天生就具备强大的基因.NiFi基本设计理念与 F ...
- cogs 1317. 数列操作C 区间修改 区间查询
1317. 数列操作C ★★★ 输入文件:shuliec.in 输出文件:shuliec.out 简单对比时间限制:1 s 内存限制:128 MB [题目描述] 假设有一个长度为 n( ...
- 已知词频生成词云图(数据库到生成词云)--generate_from_frequencies(WordCloud)
词云图是根据词出现的频率生成词云,词的字体大小表现了其频率大小. 写在前面: 用wc.generate(text)直接生成词频的方法使用很多,所以不再赘述. 但是对于根据generate_from_f ...
- (一)Mybatis基本配置,Statement方式,动态代理增删改查
首先明白Mybatis是干什么的,之前使用jdbc操作数据库时候要写很多语句,获取光标,连接,获取具体对象进行相应操作,代码过于繁琐,所以现在有了Mybatis,它将这个操作整合在了一起,你不需要关心 ...
- 初试kafka消息队列中间件一 (只适合初学者哈)
初试kafka消息队列中间件一 今天闲来有点无聊,然后就看了一下关于消息中间件的资料, 简单一点的理解哈,网上都说的太高大上档次了,字面意思都想半天: 也就是用作消息通知,比如你想告诉某某你喜欢他,或 ...