本篇讲解怎么生成和操作一维数组。各种数组类型创建的步骤是一样的,但是加载和保存步骤有所不同。
一.创建数组所有类型的一维数组创建都是一样的,分三步。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_I2int:Stelem_I4long:Stelem_I8float:Stelem_R4double: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_I1short:Ldelem_I2int:Ldelem_I4long:Ldelem_I8float:Ldelem_R4double: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); } }}