定义和执行动态方法DynamicMethod DynamicMethod
程序员文章站
2022-05-28 07:49:56
...
using System; using System.Reflection; using System.Reflection.Emit; public class Example { // The following constructor and private field are used to // demonstrate a method bound to an object. private int test; public Example(int test) { this.test = test; } //1、声明用于执行方法的委托类型。 考虑使用泛型委托,将需要声明的委托类型数降到最低。 //以下代码声明两种可用于 SquareIt 方法的委托类型,其中一个是泛型。 private delegate long SquareItInvoker(int input); private delegate TReturn OneParameter<TReturn, TParameter0> (TParameter0 p0); public static void Main() { // Example 1: 一个简单的动态方法 // // 2、创建用于为动态方法指定参数类型的数组。 在此示例中,唯一的参数为 int(在 Visual Basic 中为 Integer),所以数组只有一个元素。 // Type[] methodArgs = { typeof(int) }; //3、 创建 DynamicMethod。 在此示例中,该方法命名为 SquareIt。 //备注 //不需要为动态方法命名,并且不能通过名称调用它们。 多个动态方法可以具有相同的名称。 但是,名称将在调用堆栈中显示并且可用于调试。 //返回值的类型指定为 long。 该方法与包含 Example 类的模块关联,该类包含代码示例。 可以指定任何加载的模块。 动态方法的行为类似于模块级的 static 方法 // DynamicMethod squareIt = new DynamicMethod( "SquareIt", typeof(long), methodArgs, typeof(Example).Module); // 4、发出方法主体。 在此示例中,使用 ILGenerator 对象发出 Microsoft 中间语言 (MSIL)。 //也可以结合使用 DynamicILInfo 对象与非托管代码生成器,发出 DynamicMethod 的方法主体。 //此示例中的 MSIL 将该参数(一个 int)加载到堆栈上,将其转换为 long,复制 long, //然后将这两个数字相乘。 这会将平方结果保留在堆栈中,方法只需返回即可。 // ILGenerator il = squareIt.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Conv_I8); il.Emit(OpCodes.Dup); il.Emit(OpCodes.Mul); il.Emit(OpCodes.Ret); // 5、通过调用 CreateDelegate 方法创建表示动态方法的委托(在步骤 1 中声明)的实例。 //创建委托即完成该方法,任何更改方法的进一步尝试(例如,添加更多 MSIL)都将被忽略。 //以下代码使用泛型委托创建委托并调用它。 // OneParameter<long, int> invokeSquareIt = (OneParameter<long, int>) squareIt.CreateDelegate(typeof(OneParameter<long, int>)); Console.WriteLine("123456789 squared = {0}", invokeSquareIt(123456789)); // Example 2: 绑定到实例的动态方法. // // 1、创建用于为动态方法指定参数类型的数组。 //如果表示方法的委托要绑定到对象, //则第一个参数必须与委托绑定到的类型相匹配。 //在此示例中,存在两个参数,分别属于 Example 和 int // Type[] methodArgs2 = { typeof(Example), typeof(int) }; // Create a DynamicMethod. In this example the method has no // name. The return type of the method is int. The method // has access to the protected and private data of the // Example class. // DynamicMethod multiplyHidden = new DynamicMethod( "", typeof(int), methodArgs2, typeof(Example)); // Emit the method body. In this example ILGenerator is used // to emit the MSIL. DynamicMethod has an associated type // DynamicILInfo that can be used in conjunction with // unmanaged code generators. // // The MSIL loads the first argument, which is an instance of // the Example class, and uses it to load the value of a // private instance field of type int. The second argument is // loaded, and the two numbers are multiplied. If the result // is larger than int, the value is truncated and the most // significant bits are discarded. The method returns, with // the return value on the stack. // ILGenerator ilMH = multiplyHidden.GetILGenerator(); ilMH.Emit(OpCodes.Ldarg_0); FieldInfo testInfo = typeof(Example).GetField("test", BindingFlags.NonPublic | BindingFlags.Instance); ilMH.Emit(OpCodes.Ldfld, testInfo); ilMH.Emit(OpCodes.Ldarg_1); ilMH.Emit(OpCodes.Mul); ilMH.Emit(OpCodes.Ret); //通过调用 CreateDelegate(Type, Object) 方法重载创建表示动态方法的委托(在步骤 1 中声明)的实例 // OneParameter<int, int> invoke = (OneParameter<int, int>) multiplyHidden.CreateDelegate( typeof(OneParameter<int, int>), new Example(42) ); Console.WriteLine("3 * test = {0}", invoke(3)); } } /* This code example produces the following output: 123456789 squared = 15241578750190521 3 * test = 126 */
上一篇: 文件下传的若干有关问题