How to create a multidimensional array using Reflection.Emit

I want to create a multidimensional array using Reflection.Emit and set it. Like the following C # code:

int[,] nums = new int[2, 2]; nums[1, 1] = 2; 

And turn into IL code:

 IL_0000: nop IL_0001: ldc.i4.2 IL_0002: ldc.i4.2 IL_0003: newobj instance void int32[0..., 0...]::.ctor(int32, int32) IL_0008: stloc.0 IL_0009: ldloc.0 IL_000a: ldc.i4.1 IL_000b: ldc.i4.1 IL_000c: ldc.i4.2 IL_000d: call instance void int32[0..., 0...]::Set(int32, int32, int32) 

IL code to create an array:

 newobj instance void int32[0..., 0...]::.ctor(int32, int32) 

And the IL code to set the array element:

 call instance void int32[0..., 0...]::Set(int32, int32, int32) 

Which IL Generator.Emit () code matches these two IL clauses?

+8
c # emit
source share
2 answers

You can almost translate this IL orally:

 il.Emit(OpCodes.Ldc_I4_2); il.Emit(OpCodes.Ldc_I4_2); var constructor = typeof(int[,]).GetConstructor(new Type[]{ typeof(int), typeof(int) }); il.Emit(OpCodes.Newobj, constructor); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Ldc_I4_2); var setMethod = typeof(int[,]).GetMethod("Set"); il.Emit(OpCodes.Call, setMethod); 

Of course, you need to use reflection to actually get the ConstructorInfo and MethodInfo objects needed for the Newobj and Call codes.

+3
source share

Here is an example:

 DynamicMethod method = new DynamicMethod("Test" , typeof(int[,]), new Type[]{}); var generator = method.GetILGenerator(); //get the constructor that takes in 2 integers (the dimensions of the array) var constructor = typeof (int[,]) .GetConstructor(new {typeof (int), typeof (int)}); //get the Set method that takes in 3 integers; 2 indexes and the value var set_method = typeof(int[,]) .GetMethod("Set", new[] { typeof(int), typeof(int), typeof(int) }); var local = generator.DeclareLocal(typeof (int[,])); //local variable to reference the array generator.Emit(OpCodes.Ldc_I4_2); generator.Emit(OpCodes.Ldc_I4_2); generator.Emit(OpCodes.Newobj, constructor); //invoke the constructor to create the array generator.Emit(OpCodes.Stloc, local); generator.Emit(OpCodes.Ldloc, local); generator.Emit(OpCodes.Ldc_I4_1); generator.Emit(OpCodes.Ldc_I4_1); generator.Emit(OpCodes.Ldc_I4_2); generator.Emit(OpCodes.Call, set_method); //call the Set method to set the value generator.Emit(OpCodes.Ldloc, local); generator.Emit(OpCodes.Ret); var result_method = (Func<int[,]>)method.CreateDelegate(typeof (Func<int[,]>)); var result = result_method(); //returns the array 

This example creates a dynamic method that creates an array, populates the value in [1,1], and then returns this array.

+3
source share

All Articles