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

参数的加载
加载参数的指令是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. mysql8.0的连接写法

    由于mysql8.0的新特新,所以Driver要写成“com.mysql.cj.jdbc.Driver” url:"jdbc:mysql://host_address:3306/db_nam ...

  2. opencv编译

    1. clone源码 https://github.com/opencv/opencv 2. 安装cmake 3. cmake配置的时候,输出目录需要另外设置一个目录,不可以放到源码目录 4. 用cm ...

  3. jsp数据交互(一).1

    一.jsp中java小脚本1.<% java代码段%>2.<% =java表达式%>不能有分号3.<%!成员变量和函数声明%>二.注释1.<!--html注释 ...

  4. 第三章 JavaScript操作Dom对象

    常用的方法: 1.访问节点: 通过Document.getElementByXXX()获得一个指定节点-->再通过以下属性节点访问节点:第一部分:节点属性a:parentNode 返回节点的父节 ...

  5. 2.2.2python的BeautifulSoup库

    from bs4 import BeautifulSoupimport rebroken_html = '<ul class="country"><li>A ...

  6. 终极CRUD-2-用lombok提高开发效率

    目录 1 lom介绍与基本使用 2 lombok 注意点 2.1 lombok自动生成方法可以混合自己写的方法 2.2 尽量不要使用@Data 2.3 属性不要使用基本类型 2.4 小心@ToStri ...

  7. js实现字符串转JSON格式

    在浏览器前端实现字符串转JSON格式,有多种方法,总结如下: 方法1. js函数,eval() 语法: var obj = eval ("(" + txt + ")&qu ...

  8. 使用request获取访问者的真实IP

    在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...

  9. 不等"金九银十",金风八月,我早已拿下字节跳动的offer

    字节跳动,我是在网上投的简历,之前也投过一次,简历都没通过删选,后来让师姐帮我改了一下简历,重新投另一个部门,获得了面试机会.7月23日,中午HR打电话过来预约了下午4点半面试,说会在线写代码,让我准 ...

  10. 最基础的 ant build 脚本

    最基础的 ant build 脚本,根据项目,自行进行修改 <?xml version="1.0" encoding="UTF-8" ?> < ...