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

参数的加载
加载参数的指令是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. MicroPython TPYBoard v201 简易家庭气象站的实现过程

    转载请注明文章来源,更多教程可自助参考docs.tpyboard.com,QQ技术交流群:157816561,公众号:MicroPython玩家汇 前言 上一篇教程中我们实现了一个简单网页的显示.本篇 ...

  2. Git 的常用的命令

    之前一直在使用SVN作为版本管理工具,现在项目要求使用Git,下面简单记录一下一些常用的命令.关于原理和使用方式的详细说明,具体教程参考的廖雪峰的git教程. 1. github 账号的申请. 2. ...

  3. http状态码 400-499

    类比 服务器:便利店 客户端:客人 http报文:中文语言+钱 400-499 客户的错误 400 :服务器不理解客服端请求的意思是什么,如请求报文损坏 举例: 客户端:@#!3&* 服务器: ...

  4. SpringBoot的yml配置

    Spring Boot的yml配置 #开发配置 spring: data: solr: host: http://localhost:6789/solr/mote mvc: view: # 页面默认前 ...

  5. 2019前端面试系列——HTTP、浏览器面试题

    浏览器存储的方式有哪些 特性 cookie localStorage sessionStorage indexedDB 数据生命周期 一般由服务器生成,可以设置过期时间 除非被清理,否则一直存在 页面 ...

  6. spring 的权限控制:security

    下面我们将实现关于Spring Security3的一系列教程. 最终的目标是整合Spring Security + Spring3MVC 完成类似于SpringSide3中mini-web的功能. ...

  7. Vmware Exsi使用简要说明

    界面介绍 Exsi的管理工具可以用vSphere Client来管理虚拟机.管理虚拟的网络交换机.管理物理机的内存.物理机的硬盘.物理机的CPU等资源.界面的大致介绍如下图. 资源分配 创建内存.CP ...

  8. 【React踩坑记三】React项目报错Can't perform a React state update on an unmounted component

    意思为:我们不能在组件销毁后设置state,防止出现内存泄漏的情况 分析出现问题的原因: 我这里在组件加载完成的钩子函数里调用了一个EventBus的异步方法,如果监听到异步方法,则会更新state中 ...

  9. 转载 | embed用法(网站中视频、音频的添加)

    网站中添加视频: <embed src="http://player.video.qiyi.com/390cf6c74450e4c70b7bd2d883169914/0/0/w_19r ...

  10. hadoop的基础思想

    转载 http://www.superwu.cn/2014/01/10/963 1.1.1. hadoop的核心思想 Hadoop包括两大核心,分布式存储系统和分布式计算系统.1.1.1.1. 分布式 ...