`
wyf
  • 浏览: 436640 次
  • 性别: Icon_minigender_1
  • 来自: 唐山
社区版块
存档分类
最新评论

定义和执行动态方法DynamicMethod

阅读更多
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
 */

 

分享到:
评论

相关推荐

    Emit学习之旅

    你可以指定方法名、返回类型、参数类型和方法的访问修饰符。 - `System.Reflection.Emit.OpCodes`:这个枚举包含了所有可能的IL指令,如`Ldc_I4`(加载整数到堆栈)、`Add`(加法运算)、`Call`(调用方法)等。 -...

    动态方法和CLR的乐趣(第2部分)

    动态方法是指在程序运行时编译和创建的方法,而不是在编译阶段静态定义。这种技术允许程序员在运行时生成和执行代码,提供了极大的灵活性和效率。C# 4.0及其后续版本引入了`System.Reflection.Emit`命名空间,使得...

    “在c#编写的软件中动态地编译新的代码”对应的源码下载

    在C#编程环境中,动态编译新的代码是一项高级特性,它允许程序在运行时创建、编译和执行新的代码段。这种技术对于实现插件架构、热更新或自定义脚本系统非常有用。本文将深入探讨如何在C#中实现这一功能,并提供一个...

    C# 面向切面编程实例

    动态代理如System.Reflection.Emit或System.Linq.Expressions可以用来在运行时创建类型,这些类型在调用实际目标方法之前或之后执行额外的逻辑。静态代理则在编译时完成这个工作,如PostSharp库提供的特性编程。 ...

    dynamic-api-caller-dotnet:一个可以在运行时使用 Reflection.Emit 动态调用 Windows API 函数的类

    - `Reflection.Emit`提供了几个类,如`TypeBuilder`、`MethodBuilder`、`ILGenerator`,它们用于构建类型和方法的IL代码。 - `ILGenerator`是关键,它允许开发者通过方法调用生成IL指令,如`(OpCodes.Call, ...

    ArchAssembler:.NET 中的 x86x64 代码发射器

    Reflection.Emit允许程序在运行时动态生成类型、方法和IL代码。ArchAssembler则进一步封装了这些API,提供了更友好的接口来生成x86和x64的机器码。它将汇编指令映射到.NET的OpCodes,然后在内存中构建方法,并最终...

    C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式) (Level 300)

    - System.Proxy中的DynamicMethod和Delegate类也可以帮助构建动态代理,用于实现拦截器和AOP。 通过理解并熟练运用代理模式,开发者可以更好地设计和重构系统,提高代码的可维护性和扩展性。在C#中,代理模式的...

    ILDynamics:一个有助于动态函数生成的库!

    在这个例子中,我们定义了一个名为“Add”的动态方法,接受两个整数参数并返回它们的和。通过`GetILGenerator`获取IL生成器后,我们向IL流中添加了加载参数、执行加法运算和返回结果的指令。 ### 应用场景 ...

    线轴代理

    这些工具可以让我们在运行时动态地创建类型和方法,从而构建出能够拦截和增强调用行为的代理类。此外,System.Runtime.Remoting和System.Net命名空间也提供了实现代理服务的基础工具,例如Remoting技术可用于实现...

    在VC中彻底玩转Excel

    如果Excel没有运行,则可以使用`app-&gt;DynamicMethod("Application", (void*)0);`来创建一个新的Excel实例。 4. **操作Excel**: - **打开工作簿**:使用`books-&gt;Open`方法。 - **新建工作簿**:使用`books-&gt;Add`...

Global site tag (gtag.js) - Google Analytics