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

参数的加载
加载参数的指令是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. Python入门基础(9)__面向对象编程_3

    继承 子类自动继承父类的所有方法和属性 继承的语法: class 类名(父类名) pass 1.子类继承父类,可以直接使用父类中已经封装好的方法,不需要再次开发 2.子类可以根据需求,封装自己特有的属 ...

  2. Cobbler-自动化部署神器

    Cobbler-自动化部署神器 前言: 网络安装服务器套件 Cobbler(补鞋匠)从前,我们一直在做装机民工这份很有前途的职业.自打若干年前 Red Hat 推出了 Kickstart,此后我们顿觉 ...

  3. 最新try2hack全详解

    第一题http://www.try2hack.nl/levels/: 方法:直接右键看网页源码 第二题http://www.try2hack.nl/levels/level2-xfdgnh.xhtml ...

  4. div span img对齐,垂直居中对齐问题

    我想你们在前端开发中或多或少都遇到过这种问题,文字和图片不能平齐,很是头疼. HTML代码: <div class="">小太阳<span>小太阳</ ...

  5. jboss反序列化漏洞复现(CVE-2017-7504)

    jboss反序列化漏洞复现(CVE-2017-7504) 一.漏洞描述 Jboss AS 4.x及之前版本中,JbossMQ实现过程的JMS over HTTP Invocation Layer的HT ...

  6. 【iOS】Signing for "project_name" requires a development team. Select a development team in the project editor

    Xcode 8.3.2 运行 GitHub 上下载的代码时报了这个错. 解决方法: 单击工程名 --> Signing --> Team --> 选择对应的Account(如果没有A ...

  7. 【iOS】打印方法名

    为了便于追踪程序运行过程,可以在日志打印方法名,示例代码如下: NSLog(@"%@", NSStringFromSelector(_cmd)); 结果如图所示: 此外,在多个中, ...

  8. 【Python-Django后端】用户注册通用逻辑,用户名、手机号重名检测,注册成功后状态保持!!!

    用户注册后端逻辑 1. 接收参数 username = request.POST.get('username') password = request.POST.get('password') pas ...

  9. RocketMQ中Broker的启动源码分析(一)

    在RocketMQ中,使用BrokerStartup作为启动类,相较于NameServer的启动,Broker作为RocketMQ的核心可复杂得多 [RocketMQ中NameServer的启动源码分 ...

  10. Hadoop 系列(二)—— 集群资源管理器 YARN

    一.hadoop yarn 简介 Apache YARN (Yet Another Resource Negotiator) 是 hadoop 2.0 引入的集群资源管理系统.用户可以将各种服务框架部 ...