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);
        }
    }
}
View Code
原文地址:https://www.cnblogs.com/tkt2016/p/8723036.html