Information
The topic you requested is included in another documentation set. For convenience, it's displayed below. Choose Switch to see the topic in its original location.

How to: Define and Execute Dynamic Methods

The following procedures show how to define and execute a simple dynamic method and a dynamic method bound to an instance of a class. For more information on dynamic methods, see the DynamicMethod class and Reflection Emit Dynamic Method Scenarios.

To define and execute a dynamic method

  1. Declare a delegate type to execute the method. Consider using a generic delegate to minimize the number of delegate types you need to declare. The following code declares two delegate types that could be used for the SquareIt method, and one of them is generic.

    private delegate long SquareItInvoker(int input);
    
    private delegate TReturn OneParameter<TReturn, TParameter0>
        (TParameter0 p0);
    
  2. Create an array that specifies the parameter types for the dynamic method. In this example, the only parameter is an int (Integer in Visual Basic), so the array has only one element.

    Type[] methodArgs = {typeof(int)};
    
  3. Create a DynamicMethod. In this example the method is named SquareIt.

    NoteNote:

    It is not necessary to give dynamic methods names, and they cannot be invoked by name. Multiple dynamic methods can have the same name. However, the name appears in call stacks and can be useful for debugging.

    The type of the return value is specified as long. The method is associated with the module that contains the Example class, which contains the example code. Any loaded module could be specified. The dynamic method acts like a module-level static method (Shared in Visual Basic).

    DynamicMethod squareIt = new DynamicMethod(
        "SquareIt", 
        typeof(long), 
        methodArgs, 
        typeof(Example).Module);
    
  4. Emit the method body. In this example, an ILGenerator object is used to emit the Microsoft intermediate language (MSIL). Alternatively, a DynamicILInfo object can be used in conjunction with unmanaged code generators to emit the method body for a DynamicMethod.

    The MSIL in this example loads the argument, which is an int, onto the stack, converts it to a long, duplicates the long, and multiplies the two numbers. This leaves the squared result on the stack, and all the method has to do is return.

    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. Create an instance of the delegate (declared in step 1) that represents the dynamic method by calling the CreateDelegate method. Creating the delegate completes the method, and any further attempts to change the method — for example, adding more MSIL — are ignored. The following code creates the delegate and invokes it, using a generic delegate.

    OneParameter<long, int> invokeSquareIt = 
        (OneParameter<long, int>)
        squareIt.CreateDelegate(typeof(OneParameter<long, int>));
    
    Console.WriteLine("123456789 squared = {0}",
        invokeSquareIt(123456789));
    

To define and execute a dynamic method that is bound to an object

  1. Declare a delegate type to execute the method. Consider using a generic delegate to minimize the number of delegate types you need to declare. The following code declares a generic delegate type that can be used to execute any method with one parameter and a return value, or a method with two parameters and a return value if the delegate is bound to an object.

    private delegate TReturn OneParameter<TReturn, TParameter0>
        (TParameter0 p0);
    
  2. Create an array that specifies the parameter types for the dynamic method. If the delegate representing the method is to be bound to an object, the first parameter must match the type the delegate is bound to. In this example, there are two parameters, of type Example and type int (Integer in Visual Basic).

    Type[] methodArgs2 = { typeof(Example), typeof(int) };
    
  3. Create a DynamicMethod. In this example the method has no name. The type of the return value is specified as int (Integer in Visual Basic). The method has access to the private and protected members of the Example class.

    DynamicMethod multiplyHidden = new DynamicMethod(
        "", 
        typeof(int), 
        methodArgs2, 
        typeof(Example));
    
  4. Emit the method body. In this example, an ILGenerator object is used to emit the Microsoft intermediate language (MSIL). Alternatively, a DynamicILInfo object can be used in conjunction with unmanaged code generators to emit the method body for a DynamicMethod.

    The MSIL in this example 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);
    
  5. Create an instance of the delegate (declared in step 1) that represents the dynamic method by calling the CreateDelegate(Type, Object) method overload. Creating the delegate completes the method, and any further attempts to change the method — for example, adding more MSIL — are ignored.

    NoteNote:

    You can call the CreateDelegate method multiple times to create delegates bound to other instances of the target type.

    The following code binds the method to a new instance of the Example class whose private test field is set to 42. That is, each time the delegate is invoked the instance of Example is passed to the first parameter of the method.

    The delegate OneParameter is used because the first parameter of the method always receives the instance of Example. When the delegate is invoked, only the second parameter is required.

    OneParameter<int, int> invoke = (OneParameter<int, int>)
        multiplyHidden.CreateDelegate(
            typeof(OneParameter<int, int>), 
            new Example(42)
        );
    
    Console.WriteLine("3 * test = {0}", invoke(3));
    

The following code example demonstrates a simple dynamic method and a dynamic method bound to an instance of a class.

The simple dynamic method takes one argument, a 32-bit integer, and returns the 64-bit square of that integer. A generic delegate is used to invoke the method.

The second dynamic method has two parameters, of type Example and type int (Integer in Visual Basic). When the dynamic method has been created, it is bound to an instance of Example, using a generic delegate that has one argument of type int. The delegate does not have an argument of type Example because the first parameter of the method always receives the bound instance of Example. When the delegate is invoked, only the int argument is supplied. This dynamic method accesses a private field of the Example class and returns the product of the private field and the int argument.

The code example defines delegates that can be used to execute the methods.

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; }

    // Declare delegates that can be used to execute the completed  
    // SquareIt dynamic method. The OneParameter delegate can be  
    // used to execute any method with one parameter and a return 
    // value, or a method with two parameters and a return value 
    // if the delegate is bound to an object. 
    // 
    private delegate long SquareItInvoker(int input);

    private delegate TReturn OneParameter<TReturn, TParameter0>
        (TParameter0 p0);

    public static void Main()
    {
        // Example 1: A simple dynamic method. 
        // 
        // Create an array that specifies the parameter types for the 
        // dynamic method. In this example the only parameter is an  
        // int, so the array has only one element. 
        //
        Type[] methodArgs = {typeof(int)};

        // Create a DynamicMethod. In this example the method is 
        // named SquareIt. It is not necessary to give dynamic  
        // methods names. They cannot be invoked by name, and two 
        // dynamic methods can have the same name. However, the  
        // name appears in calls stacks and can be useful for 
        // debugging.  
        // 
        // In this example the return type of the dynamic method 
        // is long. The method is associated with the module that  
        // contains the Example class. Any loaded module could be 
        // specified. The dynamic method is like a module-level 
        // static method. 
        //
        DynamicMethod squareIt = new DynamicMethod(
            "SquareIt", 
            typeof(long), 
            methodArgs, 
            typeof(Example).Module);

        // 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 argument, which is an int, onto the  
        // stack, converts the int to a long, duplicates the top 
        // item on the stack, and multiplies the top two items on the 
        // stack. This leaves the squared number on the stack, and  
        // all the method has to do is return. 
        //
        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);

        // Create a delegate that represents the dynamic method.  
        // Creating the delegate completes the method, and any further  
        // attempts to change the method (for example, by adding more 
        // MSIL) are ignored. The following code uses a generic  
        // delegate that can produce delegate types matching any 
        // single-parameter method that has a return type. 
        //
        OneParameter<long, int> invokeSquareIt = 
            (OneParameter<long, int>)
            squareIt.CreateDelegate(typeof(OneParameter<long, int>));

        Console.WriteLine("123456789 squared = {0}",
            invokeSquareIt(123456789));

        // Example 2: A dynamic method bound to an instance. 
        // 
        // Create an array that specifies the parameter types for a 
        // dynamic method. If the delegate representing the method 
        // is to be bound to an object, the first parameter must  
        // match the type the delegate is bound to. In the following 
        // code the bound instance is of the Example class.  
        //
        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);

        // Create a delegate that represents the dynamic method.  
        // Creating the delegate completes the method, and any further  
        // attempts to change the method � for example, by adding more 
        // MSIL � are ignored.  
        //  
        // The following code binds the method to a new instance 
        // of the Example class whose private test field is set to 42. 
        // That is, each time the delegate is invoked the instance of 
        // Example is passed to the first parameter of the method. 
        // 
        // The delegate OneParameter is used, because the first 
        // parameter of the method receives the instance of Example. 
        // When the delegate is invoked, only the second parameter is 
        // required.  
        //
        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
 */

  • The code contains the C# using statements (Imports in Visual Basic) necessary for compilation.

  • No additional assembly references are required.

  • Compile the code at the command line using csc.exe, vbc.exe, or cl.exe. To compile the code in Visual Studio, place it in a console application project template.

Was this page helpful?
(1500 characters remaining)
Thank you for your feedback

Community Additions

Show:
© 2014 Microsoft