MSIL实用指南-一维数组的操作
本篇讲解怎么生成和操作一维数组。各种数组类型创建的步骤是一样的,但是加载和保存步骤有所不同。
一.创建数组
所有类型的一维数组创建都是一样的,分三步。
1.加载数组长度
2.生成指令 Newarr <数组成员类型>
3.保存
实例代码:
ilGenerator.Emit(OpCodes.Ldc_I4_S, (sbyte)100); ilGenerator.Emit(OpCodes.Newarr, typeof(int)); ilGenerator.Emit(OpCodes.Stloc_0);
二.数组的成员保存
这里的数组类型是byte、short、int、long、float、double和其它。它们的保存到成员的步骤是相似的。
首先以int型为例,它有四步。
1.加载数组变量
2.加载索引号
3.加载值
4.生成Stelem_I4指令
实例程序:
ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ldc_I4_0); ilGenerator.Emit(OpCodes.Ldc_I4, int.MaxValue); ilGenerator.Emit(OpCodes.Stelem_I4);
其它几种类型的前三步和int类型是一样的,只有最后一步不同,它们各有各的指令,对应关系是
byte:Stelem_I1
short:Stelem_I2
int:Stelem_I4
long:Stelem_I8
float:Stelem_R4
double:Stelem_R8
其它:Stelem_Ref
三.其它类型的成员加载
加载也和保存类似。首先以int型数组为例,要分三步
1.加载数组变量
2.加载索引号
3.生成Ldelem_I4指令
实例程序:
ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ldc_I4_0); ilGenerator.Emit(OpCodes.Ldelem_I4);
其它类型的第三步指令各不相同,对应关系是
byte:Ldelem_I1
short:Ldelem_I2
int:Ldelem_I4
long:Ldelem_I8
float:Ldelem_R4
double:Ldelem_R8
其它:Ldelem_Ref
完整的程序如下
using System; using System.Reflection; using System.Reflection.Emit; namespace LX1_ILDemo { public class Demo21_ArrayOne { static string binaryName = "Demo21_ArrayOne.dll"; static string namespaceName = "LX1_ILDemo"; static string typeName = "DemoArrayOne"; static AssemblyBuilder assemblyBuilder; static ModuleBuilder moduleBuilder; static TypeBuilder typeBuilder; static MethodBuilder methodBuilder; static ILGenerator ilGenerator; public static void Generate() { InitAssembly(); typeBuilder = moduleBuilder.DefineType(namespaceName + "." + typeName, TypeAttributes.Public | TypeAttributes.Abstract); methodBuilder = typeBuilder.DefineMethod("TestArray", MethodAttributes.Public | MethodAttributes.Static, typeof(void), new Type[] { }); ilGenerator = methodBuilder.GetILGenerator(); LocalBuilder localBuilderv1 = ilGenerator.DeclareLocal(typeof(int[])); LocalBuilder localBuilderv2 = ilGenerator.DeclareLocal(typeof(int)); LocalBuilder localBuilderv3 = ilGenerator.DeclareLocal(typeof(float[])); LocalBuilder localBuilderv4 = ilGenerator.DeclareLocal(typeof(float)); LocalBuilder localBuilderv5 = ilGenerator.DeclareLocal(typeof(string[])); LocalBuilder localBuilderv6 = ilGenerator.DeclareLocal(typeof(string)); ilGenerator.Emit(OpCodes.Nop); Generate_IntArray(); Generate_FloatArray(); Generate_StringArray(); ilGenerator.Emit(OpCodes.Ret); SaveAssembly(); Console.WriteLine("生成成功"); } static void Generate_IntArray() { ilGenerator.Emit(OpCodes.Ldc_I4_S, (sbyte)100); ilGenerator.Emit(OpCodes.Newarr, typeof(int)); ilGenerator.Emit(OpCodes.Stloc_0); ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ldc_I4_0); ilGenerator.Emit(OpCodes.Ldc_I4, int.MaxValue); ilGenerator.Emit(OpCodes.Stelem_I4); ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ldc_I4_0); ilGenerator.Emit(OpCodes.Ldelem_I4); ilGenerator.Emit(OpCodes.Stloc_1); } static void Generate_FloatArray() { ilGenerator.Emit(OpCodes.Ldc_I4_S, (sbyte)20); ilGenerator.Emit(OpCodes.Newarr, typeof(float)); ilGenerator.Emit(OpCodes.Stloc_2); ilGenerator.Emit(OpCodes.Ldloc_2); ilGenerator.Emit(OpCodes.Ldc_I4_0); ilGenerator.Emit(OpCodes.Ldc_I4, float.MaxValue); ilGenerator.Emit(OpCodes.Stelem_R4); ilGenerator.Emit(OpCodes.Ldloc_2); ilGenerator.Emit(OpCodes.Ldc_I4_0); ilGenerator.Emit(OpCodes.Ldelem_R4); ilGenerator.Emit(OpCodes.Stloc_3); } static void Generate_StringArray() { ilGenerator.Emit(OpCodes.Ldc_I4_S, (sbyte)30); ilGenerator.Emit(OpCodes.Newarr, typeof(string)); ilGenerator.Emit(OpCodes.Stloc_S, (sbyte)4); ilGenerator.Emit(OpCodes.Ldloc_S, (sbyte)4); ilGenerator.Emit(OpCodes.Ldc_I4_0); ilGenerator.Emit(OpCodes.Ldstr,"test string"); ilGenerator.Emit(OpCodes.Stelem_Ref); ilGenerator.Emit(OpCodes.Ldloc_S, (sbyte)4); ilGenerator.Emit(OpCodes.Ldc_I4_0); ilGenerator.Emit(OpCodes.Ldelem_Ref); ilGenerator.Emit(OpCodes.Stloc_S, (sbyte)5); } 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); } } }