从IL构造方法引用集合

编程入门 行业动态 更新时间:2024-10-28 01:26:05
本文介绍了从IL构造方法引用集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在使用反射构建动态方法。大多数教程和文档(例如如何:定义和定义执行动态方法或动态创建方法并执行)显示一个非常简单的示例。

I am building a dynamic method using reflection. Most tutorials and documentation (e.g. How to: Define and Execute Dynamic Methods or Creating method dynamically, and executing it) show a very simple example.

我试图找到一种从动态程序集中引用另一个程序集的方法。

I trying to find a way to reference another assembly from the dynamic assembly.

例如,我希望能够通过使用 Reflection.Emit 构造以下函数。

For example, I would like to be able to construct the following function by using Reflection.Emit.

public static void f(int n) { int[] arr = new arr[n]; return arr.Max(); }

这样做的常见方式是什么?

What would be the common way of doing this?

推荐答案

获取有效IL指令的最可靠方法是用高级语言创建代码,对其进行编译和反编译。接下来,您可以使用 Reflection.Emit 重新创建指令。

The most reliable way to get valid IL instructions is to create your code in a high level language, compile it and decompile it. Next you can recreate the instructions with Reflection.Emit.

我更改了示例函数,否则它的可测试性不好,因为结果将始终相同:

I changed your example function otherwise its not good testable because the result would be always the same:

public static int f(int n) { int[] arr = Enumerable.Range(0, n).ToArray(); return arr.Max(); }

作为调试程序构建,ILDAsm给了我们(释放将导致更少的指令,但是

Build as debug, ILDasm gives us (Release would result in far fewer instructions but there is not too much to see then):

.method public hidebysig static int32 f(int32 n) cil managed { // Code size 25 (0x19) .maxstack 2 .locals init ([0] int32[] arr, [1] int32 V_1) IL_0000: nop IL_0001: ldc.i4.0 IL_0002: ldarg.0 IL_0003: call class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> [System.Core]System.Linq.Enumerable::Range(int32, int32) IL_0008: call !!0[] [System.Core]System.Linq.Enumerable::ToArray<int32>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>) IL_000d: stloc.0 IL_000e: ldloc.0 IL_000f: call int32 [System.Core]System.Linq.Enumerable::Max(class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>) IL_0014: stloc.1 IL_0015: br.s IL_0017 IL_0017: ldloc.1 IL_0018: ret } // end of method Program::f

现在,您可以使用MethodBuilder / DynamicMethod和ILGenerator重新创建此方法的每个方面。

Now you can recreate every aspect of this method with the MethodBuilder/DynamicMethod and the ILGenerator.

public static int fNew(int n) { var da = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("tempAsm"), AssemblyBuilderAccess.RunAndSave); var dm = da.DefineDynamicModule("tempAsm", "tempAsm.dll"); var dt = dm.DefineType("dynType"); var d = dt.DefineMethod("f", MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, CallingConventions.Standard, typeof (int), new[] {typeof (int)}); var il = d.GetILGenerator(); il.DeclareLocal(typeof (int[])); il.DeclareLocal(typeof (int)); var range = typeof (Enumerable).GetMethod(nameof(Enumerable.Range)); var toArray = typeof (Enumerable).GetMethod(nameof(Enumerable.ToArray)).MakeGenericMethod(typeof (int)); var max = typeof (Enumerable).GetMethod(nameof(Enumerable.Max), new[] {typeof (IEnumerable<>).MakeGenericType(typeof (int))}); if (range == null || toArray == null || max == null) throw new Exception(); var branchTarget = il.DefineLabel(); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, range); il.Emit(OpCodes.Call, toArray); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Call, max); il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Br_S, branchTarget); il.MarkLabel(branchTarget); il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Ret); var bakedType = dt.CreateType(); da.Save("tempAsm.dll"); var x = bakedType.GetMethod("f"); return (int) x.Invoke(null, new object[] {n}); }

测试一下:

static void Main(string[] args) { Console.WriteLine(f(10)); Console.WriteLine(fNew(10)); }

,它应该可以工作:

9 9

更多推荐

从IL构造方法引用集合

本文发布于:2023-11-17 03:44:35,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1608700.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:方法   IL

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!