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 ...
随机推荐
- Java_Map接口
Map接口 1.1 Map接口概述 我们通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同,如下图. Collection中的集合,元素是孤立存在 ...
- 如何在 Centos7 中安装 gcc
系统环境:Centos7.4 今天在安装 Nodejs8.7 的时候,报了一个警告: WARNING: C++ Compiler too old, need g++ 4.9.4 or clang++ ...
- linux初学者-磁盘阵列篇
linux初学者-磁盘阵列篇 在磁盘的使用中,有时候需要提高磁盘的读写数据速度,就要用到磁盘组——raid,也就是磁盘阵列. 磁盘阵列是由最少两块以上的磁盘组成的,raid有许多模式,在这里将介绍其中 ...
- 使用Java实现数据库编程 项目(宠物商店)
创建数据库代码: DROP DATABASE IF EXISTS petShop; CREATE DATABASE petShop; USE petShop; /*创建表*/ CREATE TABLE ...
- WIZnet-io6Library下载及使用
概观 io6Library是一个IPv6集成库,可以轻松集成和管理使用WIZnet硬连线双TCP / IP堆栈控制器(WIZCHIP)产品系列的用户应用程序. io6Library用于管理依赖于用户特 ...
- Ant Design Pro 脚手架+umiJS 实践总结
一.简介 1.Ant Design Pro Ant Design Pro是一款搭建中后台管理控制台的脚手架 ,基于React,dva.js,Ant Design (1)其中dva主要是控制数据流向,是 ...
- H5中的history方法Api介绍
最近公司在做一个微信公众号,看了项目源码,看到项目中用到了history的Api来进行控制浏览器的历史记录及前进/后退键: 下面来跟大家一起来捋捋history的Api方法和使用: history.p ...
- 创建docker容器遇到的错误
1.问题截图 2.问题描述 出现该问题就是docker版本和系统版本不兼容导致的. 现在的系统版本和docker的版本如下: 3.问题解决 安装低版本的docker或者高版本的系统(Centos7.4 ...
- Z算法
Z算法 Z算法是一种用于字符串匹配的算法.此算法的核心在于\(z\)数组以及它的求法. (以下约定字符串下标从\(1\)开始) \(\bm z\)数组和Z-box 定义\(z\)数组:\(z_{a,i ...
- 5G标准公布,你很快又要换手机了
通常,在4G网络环境下,下载一部1G的电影只需要30秒时间,对于经历过2G和3G网络的我们来说已经非常快了. 但是听说,5G环境中下载一部同样的电影,根本不是用秒来计算的,甚至有外媒说,5G的速率会是 ...