本篇讲解怎么加载和保存参数,以及参数起始序号的确定。

参数的加载
加载参数的指令是Ldarg、Ldarg_S、Ldarg_0、Ldarg_1、Ldarg_2、Ldarg_3。
Ldarg_0是加载第0个参数,例子 ilGenerator.Emit(OpCodes.Ldarg_0);
Ldarg_1是加载第1个参数,例子 ilGenerator.Emit(OpCodes.Ldarg_1);
Ldarg_2是加载第2个参数,例子 ilGenerator.Emit(OpCodes.Ldarg_2);
Ldarg_3是加载第3个参数,例子 ilGenerator.Emit(OpCodes.Ldarg_3);
Ldarg_S是加载次序为0到255的参数,例子 ilGenerator.Emit(OpCodes.Ldarg_S,5);
Ldarg加载任意次序的参数,例子 ilGenerator.Emit(OpCodes.Ldarg,6)。

我们可以根据指令的说明实现一个方便调用的方法,源码如下

        public static void LoadArg(ILGenerator ilGenerator, int argIndex)
{
switch (argIndex)
{
case :
ilGenerator.Emit(OpCodes.Ldarg_0);
return;
case :
ilGenerator.Emit(OpCodes.Ldarg_1);
return;
case :
ilGenerator.Emit(OpCodes.Ldarg_2);
return;
case :
ilGenerator.Emit(OpCodes.Ldarg_3);
return;
}
if (argIndex > && argIndex <= )
{
ilGenerator.Emit(OpCodes.Ldarg_S, argIndex);
return;
}
else
{
ilGenerator.Emit(OpCodes.Ldarg, argIndex);
return;
}
}

参数的保存
保存参数的指令是Starg、Starg_S
Ldarg_S是保存次序为0到255的参数,例子 ilGenerator.Emit(OpCodes.Starg_S,1);
Starg加载任意次序的参数,例子 ilGenerator.Emit(OpCodes.Starg,6)。

我们可以根据指令的说明实现一个方便调用的方法,源码如下

        public static void StormArg(ILGenerator ilGenerator, int argIndex)
{
if (argIndex > 0 && argIndex <= 255)
{
ilGenerator.Emit(OpCodes.Starg_S, argIndex);
return;
}
else
{
ilGenerator.Emit(OpCodes.Starg, argIndex);
return;
}
}

  

参数起始序号的确定
参数的起始序号不一定从0开始,也可能从1开始,这是由方法是否是static决定的。
如果参数所在的方法是static修饰的,序号从0开始;
如果不是static修饰,则从0开始。

完整的一个例子如下

using System;
using System.Reflection;
using System.Reflection.Emit; namespace LX1_ILDemo
{
class Demo08_Arg
{
static string binaryName = "Demo08_Arg.exe";
static string namespaceName = "LX1_ILDemo";
static string typeName = "ArgTest"; static AssemblyBuilder assemblyBuilder;
static ModuleBuilder moduleBuilder;
static TypeBuilder typeBuilder;
static MethodBuilder mainMethod;
static MethodBuilder printStaticMethod;
static MethodBuilder printInstaceMethod;
static ConstructorBuilder constructorBuilder; static void Emit_PrintInstace()
{
printInstaceMethod = typeBuilder.DefineMethod("PrintInstanceArg", MethodAttributes.Public,
typeof(void), new Type[] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(string) });
ILGenerator printILInstaceGenerator = printInstaceMethod.GetILGenerator();
ParameterBuilder ab1 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i1");
ParameterBuilder ab2 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i2");
ParameterBuilder ab3 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i3");
ParameterBuilder ab4 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i4");
ParameterBuilder ab5 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "s5"); MethodInfo writeIntLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });
MethodInfo writeStringLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
LoadArg(printILInstaceGenerator,);
printILInstaceGenerator.Emit(OpCodes.Call, writeIntLineMethod);
LoadArg(printILInstaceGenerator, );
printILInstaceGenerator.Emit(OpCodes.Call, writeIntLineMethod);
LoadArg(printILInstaceGenerator, );
printILInstaceGenerator.Emit(OpCodes.Call, writeIntLineMethod);
LoadArg(printILInstaceGenerator, );
printILInstaceGenerator.Emit(OpCodes.Call, writeIntLineMethod);
LoadArg(printILInstaceGenerator, );
printILInstaceGenerator.Emit(OpCodes.Call, writeStringLineMethod);
printILInstaceGenerator.Emit(OpCodes.Ldstr, "world");
StormArg(printILInstaceGenerator, );
LoadArg(printILInstaceGenerator, );
printILInstaceGenerator.Emit(OpCodes.Call, writeStringLineMethod);
printILInstaceGenerator.Emit(OpCodes.Ret);
} public static void LoadArg(ILGenerator ilGenerator, int argIndex)
{
switch (argIndex)
{
case :
ilGenerator.Emit(OpCodes.Ldarg_0);
return;
case :
ilGenerator.Emit(OpCodes.Ldarg_1);
return;
case :
ilGenerator.Emit(OpCodes.Ldarg_2);
return;
case :
ilGenerator.Emit(OpCodes.Ldarg_3);
return;
}
if (argIndex > && argIndex <= )
{
ilGenerator.Emit(OpCodes.Ldarg_S, argIndex);
return;
}
else
{
ilGenerator.Emit(OpCodes.Ldarg, argIndex);
return;
}
} public static void StormArg(ILGenerator ilGenerator, int argIndex)
{
if (argIndex > && argIndex <= )
{
ilGenerator.Emit(OpCodes.Starg_S, argIndex);
return;
}
else
{
ilGenerator.Emit(OpCodes.Starg, argIndex);
return;
}
} static void Emit_PrintStatic()
{
printStaticMethod = typeBuilder.DefineMethod("PrintStaticArg", MethodAttributes.Public
| MethodAttributes.Static, typeof(void), new Type[] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(string) });
ILGenerator printILGenerator = printStaticMethod.GetILGenerator();
ParameterBuilder ab1 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i1");
ParameterBuilder ab2 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i2");
ParameterBuilder ab3 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i3");
ParameterBuilder ab4 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i4");
ParameterBuilder ab5 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "s5"); MethodInfo writeIntLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });
MethodInfo writeStringLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
printILGenerator.Emit(OpCodes.Ldarg_0);
printILGenerator.Emit(OpCodes.Call, writeIntLineMethod);
printILGenerator.Emit(OpCodes.Ldarg_1);
printILGenerator.Emit(OpCodes.Call, writeIntLineMethod);
printILGenerator.Emit(OpCodes.Ldarg_2);
printILGenerator.Emit(OpCodes.Call, writeIntLineMethod);
printILGenerator.Emit(OpCodes.Ldarg_3);
printILGenerator.Emit(OpCodes.Call, writeIntLineMethod);
printILGenerator.Emit(OpCodes.Ldarg_S,);
printILGenerator.Emit(OpCodes.Call, writeStringLineMethod);
printILGenerator.Emit(OpCodes.Ldstr, "world");
printILGenerator.Emit(OpCodes.Starg_S, );
printILGenerator.Emit(OpCodes.Ldarg_S, );
printILGenerator.Emit(OpCodes.Call, writeStringLineMethod);
printILGenerator.Emit(OpCodes.Ret);
} public static void Generate()
{
InitAssembly();
typeBuilder = moduleBuilder.DefineType( namespaceName+"."+ typeName, TypeAttributes.Public);
constructorBuilder = typeBuilder.DefineDefaultConstructor( MethodAttributes.Public);
Emit_PrintStatic();
Emit_PrintInstace();
EmitMain(); /* 设置assembly入口方法 */
assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication);
SaveAssembly();
Console.WriteLine("生成成功");
} static void EmitMain()
{
mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public
| MethodAttributes.Static, typeof(void), new Type[] { });
ILGenerator mainILGenerator = mainMethod.GetILGenerator(); mainILGenerator.Emit(OpCodes.Ldc_I4,(int));
mainILGenerator.Emit(OpCodes.Ldc_I4, (int));
mainILGenerator.Emit(OpCodes.Ldc_I4, (int));
mainILGenerator.Emit(OpCodes.Ldc_I4, (int));
mainILGenerator.Emit(OpCodes.Ldstr,"hello static");
mainILGenerator.Emit(OpCodes.Call, printStaticMethod); LocalBuilder localBuilder = mainILGenerator.DeclareLocal(typeof(string));
mainILGenerator.Emit(OpCodes.Newobj, constructorBuilder);
mainILGenerator.Emit(OpCodes.Stloc_0);
mainILGenerator.Emit(OpCodes.Ldloc_0);
mainILGenerator.Emit(OpCodes.Ldc_I4, (int));
mainILGenerator.Emit(OpCodes.Ldc_I4, (int));
mainILGenerator.Emit(OpCodes.Ldc_I4, (int));
mainILGenerator.Emit(OpCodes.Ldc_I4, (int));
mainILGenerator.Emit(OpCodes.Ldstr, "hello instance");
mainILGenerator.Emit(OpCodes.Call, printInstaceMethod); MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { });
mainILGenerator.Emit(OpCodes.Call, readKeyMethod);
mainILGenerator.Emit(OpCodes.Pop);
mainILGenerator.Emit(OpCodes.Ret); } 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实用指南-加载和保存参数的更多相关文章

  1. MSIL实用指南-加载null、string、long、float、double等值

    本篇讲述怎么加载null.string值.long值.float值.double值. 加载null不需要参数值,只要 Emit ldnull 其它几个命令要 Emit <指令> <值 ...

  2. MSIL实用指南-加载bool、sbyte、byte、char、short等值

    这一篇讲解怎么加载bool值.sbyte值.byte值.char值.short值. 加载bool值在.NET程序实际运行中,是没有true和false值的,实际上是以1和0表示它们,加载它们的指令是L ...

  3. MSIL实用指南-加载int值

    这一篇讲的是怎样加载整数值到运算栈上.这一类的指令都是以Ldc_I4开头. Ldc_I4类OpCodes的Ldc_I4字段的功能是把一个int值压入运算栈上.它的使用方法是ilGenerator.Em ...

  4. MSIL实用指南-创建方法和定义参数

    本篇讲解实现创建方法.指定参数的名称.实现参数加out和ref修饰符.以及参数加默认值. 创建方法 创建方法用类TypeAttributes的 DefineMethod(string name, Me ...

  5. Knockout应用开发指南 第六章:加载或保存JSON数据

    原文:Knockout应用开发指南 第六章:加载或保存JSON数据 加载或保存JSON数据 Knockout可以实现很复杂的客户端交互,但是几乎所有的web应用程序都要和服务器端交换数据(至少为了本地 ...

  6. MSIL实用指南-Action的生成和调用

    MSIL实用指南-Action的生成和调用 System.Action用于封装一个没有参数没有返回值的方法.这里生成需要Ldftn指令. 下面讲解怎生成如下的程序. class ActionTest ...

  7. MSIL实用指南-生成索引器

    MSIL实用指南-生成索引器 索引器是一种特殊的属性,它有参数的,也有get和set方法,属性名称一般是"Item",并且方法名称一般名称是"get_Item" ...

  8. KnockoutJS 3.X API 第七章 其他技术(1) 加载和保存JSON数据

    Knockout允许您实现复杂的客户端交互性,但几乎所有Web应用程序还需要与服务器交换数据,或至少将本地存储的数据序列化. 最方便的交换或存储数据的方式是JSON格式 - 大多数Ajax应用程序今天 ...

  9. Tensorflow模型加载与保存、Tensorboard简单使用

    先上代码: from __future__ import absolute_import from __future__ import division from __future__ import ...

随机推荐

  1. MYSQL主从复制、主主复制、双主多从配置

    一.如何配置MYSQL的主从复制? 1. 两台数据库服务器,IP分别为 192.168.216.128 和 192.168.216.129,在服务器上装MYSQL(我的配置版本为5.5.56) 2. ...

  2. 使用GDAL实现DEM的地貌晕渲图(三)

    目录 1. 原理 1) ArcMap生成彩色晕渲图 2) 彩色色带赋值 3) 颜色叠加 2. 实现 3. 结语 4. 参考 1. 原理 之前在<使用GDAL实现DEM的地貌晕渲图(一)>和 ...

  3. Rust生命周期bound用于泛型的引用

    在实际编程中,可能会出现泛型引用这种情况,我们会编写如下的代码: struct Inner<'a, T> { data: &'a T, } 会产生编译错误: error[E0309 ...

  4. 我的ubuntu kylin中mentohust的使用历程

    1首先下载mentohus 最新版下载(包括源码):http://code.google.com/p/mentohust/downloads/list 2打开终端(Ctrl+Alt+T) 输入sudo ...

  5. 夯实Java基础(十四)——Java8新的日期处理类

    1.前言 Java8之前处理日期一直是Java程序员比较头疼的问题,从Java 8之后,Java里面添加了许多的新特性,其中一个最常见也是最实用的便是日期处理的类——LocalDate.LocalDa ...

  6. 【原创】原来你竟然是这样的Chrome?!Firefox笑而不语

    书接上文 上一篇文章<[原创]用事实说话,Firefox 的性能是 Chrome 的 2 倍,Edge 的 4 倍,IE11 的 6 倍!>,我们对比了不同浏览器下FineUIPro一个页 ...

  7. SpringBoot入门及YML文件详解

    SpringBoot 简介 微框架,与 Spring4 一起诞生,基于约定.生来为了简化 spring 的配置 优点 可以快速的上手,整合了一些子项目(开源框架或者第三方开源库) 可以依赖很少的配置快 ...

  8. 基于http(s)协议的模板化爬虫设计

    声明:本文为原创,转载请注明出处 本文总共三章,前面两章废话吐槽比较多,想看结果的话,直接看第三章(后续会更新,最近忙着毕设呢,毕设也是我自己做的,关于射频卡的,有时间我也放上来,哈哈). 一,系统总 ...

  9. 【Kubernetes 系列二】从虚拟机讲到 Kubernetes 架构

    目录 什么是虚拟机? 什么是容器? Docker Kubernetes 架构 Kubernetes 对象 基础设施抽象 在认识 Kubernetes 之前,我们需了解下容器,在了解容器之前,我们得先知 ...

  10. WebService—— IDEA创建WebServices

    一.File–>New–>Project 弹出这个对话框后,照下图的勾选然后点击Next,然后填写项目名和项目路径后,点击finish. 二.生成目录如下 需要注意的有HelloWorld ...