Export (0) Print
Expand All
3 out of 4 rated this helpful - Rate this topic

DynamicMethod Class

Defines and represents a dynamic method that can be compiled, executed, and discarded. Discarded methods are available for garbage collection.

Namespace: System.Reflection.Emit
Assembly: mscorlib (in mscorlib.dll)

[ComVisibleAttribute(true)] 
public sealed class DynamicMethod : MethodInfo
/** @attribute ComVisibleAttribute(true) */ 
public final class DynamicMethod extends MethodInfo
ComVisibleAttribute(true) 
public final class DynamicMethod extends MethodInfo
Not applicable.

You can use the DynamicMethod class to generate and execute a method at run time, without having to generate a dynamic assembly and a dynamic type to contain the method. The executable code created by the just-in-time (JIT) compiler is reclaimed when the DynamicMethod object is reclaimed. Dynamic methods are the most efficient way to generate and execute small amounts of code.

A dynamic method can be anonymously hosted, or it can be logically associated with a module or with a type.

  • If the dynamic method is anonymously hosted, it is located in a system-provided assembly, and therefore is isolated from other code. By default, it does not have access to any non-public data. An anonymously hosted dynamic method can have restricted ability to skip the JIT compiler's visibility checks, if it has been granted ReflectionPermission with the System.Security.Permissions.ReflectionPermissionFlag.RestrictedMemberAccess flag. The trust level of the assembly whose non-public members are accessed by the dynamic method must be equal to, or a subset of, the trust level of the call stack that emitted the dynamic method. For more information about anonymously hosted dynamic methods, see Walkthrough: Emitting Code in Partial Trust Scenarios.

  • If the dynamic method is associated with a module that you specify, the dynamic method is effectively global to that module. It can access all types in the module and all internal (Friend in Visual Basic) members of the types. You can associate a dynamic method with any module, regardless of whether you created the module, provided that a demand for ReflectionPermission with the RestrictedMemberAccess flag can be satisfied by the call stack that includes your code. If the ReflectionPermissionFlag.MemberAccess flag is included in the grant, the dynamic method can skip the JIT compiler's visibility checks and access the private data of all types declared in the module or in any other module in any assembly.

    NoteNote:

    When you specify the module with which a dynamic method is associated, that module must not be in the system-provided assembly that is used for anonymous hosting.

  • If the dynamic method is associated with a type that you specify, it has access to all members of the type, regardless of access level. In addition, JIT visibility checks can be skipped. This gives the dynamic method access to the private data of other types declared in the same module or in any other module in any assembly. You can associate a dynamic method with any type, but your code must be granted ReflectionPermission with both the RestrictedMemberAccess and MemberAccess flags.

The following table shows which types and members are accessible to an anonymously hosted dynamic method, with and without JIT visibility checks, depending on whether ReflectionPermission with the RestrictedMemberAccess flag is granted.

 

Without RestrictedMemberAccess

With RestrictedMemberAccess

Without skipping JIT visibility checks

Public members of public types in any assembly.

Public members of public types in any assembly.

Skipping JIT visibility checks, with restrictions

Public members of public types in any assembly.

All members of all types, only in assemblies whose trust levels are equal to or less than the trust level of the assembly that emitted the dynamic method.

NoteNote:

Prior to the , emitting code required ReflectionPermission with the ReflectionPermissionFlag.ReflectionEmit flag. This permission is included by default in the FullTrust and LocalIntranet named permission sets, but not in the Internet permission set. Therefore, in earlier versions of the .NET Framework a library can be used with Internet permissions only if it has the SecurityCriticalAttribute attribute and also executes an Assert for ReflectionEmit. Such libraries require careful security review because coding errors could result in security holes. The allows code to be emitted in partial trust scenarios without issuing any security demands, because generating code is not inherently a privileged operation. That is, the generated code has no more permissions than the assembly that emits it. This allows libraries that emit code to be security transparent and removes the need to assert ReflectionEmit, which simplifies the task of writing a secure library. To use this feature, your application should target the . For more information, see The .NET Framework 3.5 Architecture.

The following table shows which types and members are accessible to a dynamic method that is associated with a module or with a type in a module.

 

Associated with module

Associated with type

Without skipping JIT visibility checks

Public and internal members of public, internal, and private types in the module.

Public members of public types in any assembly.

All members of the associated type. Public and internal members of all the other types in the module.

Public members of public types in any assembly.

Skipping JIT visibility checks

All members of all types in any assembly.

All members of all types in any assembly.

A dynamic method that is associated with a module has the permissions of that module. A dynamic method that is associated with a type has the permissions of the module containing that type.

Dynamic methods and their parameters do not have to be named, but you can specify names to assist in debugging. Custom attributes are not supported on dynamic methods or their parameters.

Although dynamic methods are static methods (Shared methods in Visual Basic), the relaxed rules for delegate binding introduced in the .NET Framework 2.0 allow a dynamic method to be bound to an object, so that it acts like an instance method when called using that delegate instance. An example that demonstrates this is provided for the CreateDelegate(Type,Object) method overload.

NoteNote:

In the .NET Framework 2.0, dynamic methods do not support symbol information, that is, local variable names and line-number mapping. This limitation might be removed in a future version. You can use AssemblyBuilder during development to simplify debugging the generated Microsoft intermediate language (MSIL), and then switch to dynamic methods during final deployment, because the ILGenerator calls are the same in both cases.

The following code example creates a dynamic method that takes two parameters. The example emits a simple function body that prints the first parameter to the console, and the example uses the second parameter as the return value of the method. The example completes the method by creating a delegate, invokes the delegate with different parameters, and finally invokes the dynamic method using the Invoke method.

using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Globalization;

public class Test
{
    // Declare a delegate type that can be used to execute the completed
    // dynamic method. 
    private delegate int HelloDelegate(string msg, int ret);

    public static void Main()
    {
        // Create an array that specifies the types of the parameters
        // of the dynamic method. This dynamic method has a String
        // parameter and an Integer parameter.
        Type[] helloArgs = {typeof(string), typeof(int)};

        // Create a dynamic method with the name "Hello", a return type
        // of Integer, and two parameters whose types are specified by
        // the array helloArgs. Create the method in the module that
        // defines the String class.
        DynamicMethod hello = new DynamicMethod("Hello", 
            typeof(int), 
            helloArgs, 
            typeof(string).Module);

        // Create an array that specifies the parameter types of the
        // overload of Console.WriteLine to be used in Hello.
        Type[] writeStringArgs = {typeof(string)};
        // Get the overload of Console.WriteLine that has one
        // String parameter.
        MethodInfo writeString = typeof(Console).GetMethod("WriteLine", 
            writeStringArgs);

        // Get an ILGenerator and emit a body for the dynamic method,
        // using a stream size larger than the IL that will be
        // emitted.
        ILGenerator il = hello.GetILGenerator(256);
        // Load the first argument, which is a string, onto the stack.
        il.Emit(OpCodes.Ldarg_0);
        // Call the overload of Console.WriteLine that prints a string.
        il.EmitCall(OpCodes.Call, writeString, null);
        // The Hello method returns the value of the second argument;
        // to do this, load the onto the stack and return.
        il.Emit(OpCodes.Ldarg_1);
        il.Emit(OpCodes.Ret);

        // Add parameter information to the dynamic method. (This is not
        // necessary, but can be useful for debugging.) For each parameter,
        // identified by position, supply the parameter attributes and a 
        // parameter name.
        ParameterBuilder parameter1 = hello.DefineParameter(
            1, 
            ParameterAttributes.In, 
            "message"
        );
        ParameterBuilder parameter2 = hello.DefineParameter(
            2, 
            ParameterAttributes.In, 
            "valueToReturn"
        );

        // Create a delegate that represents the dynamic method. This
        // action completes the method. Any further attempts to
        // change the method are ignored.
        HelloDelegate hi = 
            (HelloDelegate) hello.CreateDelegate(typeof(HelloDelegate));

        // Use the delegate to execute the dynamic method.
        Console.WriteLine("\r\nUse the delegate to execute the dynamic method:");
        int retval = hi("\r\nHello, World!", 42);
        Console.WriteLine("Invoking delegate hi(\"Hello, World!\", 42) returned: " + retval);

        // Execute it again, with different arguments.
        retval = hi("\r\nHi, Mom!", 5280);
        Console.WriteLine("Invoking delegate hi(\"Hi, Mom!\", 5280) returned: " + retval);

        Console.WriteLine("\r\nUse the Invoke method to execute the dynamic method:");
        // Create an array of arguments to use with the Invoke method.
        object[] invokeArgs = {"\r\nHello, World!", 42};
        // Invoke the dynamic method using the arguments. This is much
        // slower than using the delegate, because you must create an
        // array to contain the arguments, and value-type arguments
        // must be boxed.
        object objRet = hello.Invoke(null, BindingFlags.ExactBinding, null, invokeArgs, new CultureInfo("en-us"));
        Console.WriteLine("hello.Invoke returned: " + objRet);

        Console.WriteLine("\r\n ----- Display information about the dynamic method -----");
        // Display MethodAttributes for the dynamic method, set when 
        // the dynamic method was created.
        Console.WriteLine("\r\nMethod Attributes: {0}", hello.Attributes);

        // Display the calling convention of the dynamic method, set when the 
        // dynamic method was created.
        Console.WriteLine("\r\nCalling convention: {0}", hello.CallingConvention);

        // Display the declaring type, which is always null for dynamic
        // methods.
        if (hello.DeclaringType == null)
        {
            Console.WriteLine("\r\nDeclaringType is always null for dynamic methods.");
        }
        else
        {
            Console.WriteLine("DeclaringType: {0}", hello.DeclaringType);
        }

        // Display the default value for InitLocals.
        if (hello.InitLocals)
        {
            Console.Write("\r\nThis method contains verifiable code.");
        }
        else
        {
            Console.Write("\r\nThis method contains unverifiable code.");
        }
        Console.WriteLine(" (InitLocals = {0})", hello.InitLocals);

        // Display the module specified when the dynamic method was created.
        Console.WriteLine("\r\nModule: {0}", hello.Module);

        // Display the name specified when the dynamic method was created.
        // Note that the name can be blank.
        Console.WriteLine("\r\nName: {0}", hello.Name);

        // For dynamic methods, the reflected type is always null.
        if (hello.ReflectedType == null)
        {
            Console.WriteLine("\r\nReflectedType is null.");
        }
        else
        {
            Console.WriteLine("\r\nReflectedType: {0}", hello.ReflectedType);
        }

        if (hello.ReturnParameter == null)
        {
            Console.WriteLine("\r\nMethod has no return parameter.");
        }
        else
        {
            Console.WriteLine("\r\nReturn parameter: {0}", hello.ReturnParameter);
        }

        // If the method has no return type, ReturnType is System.Void.
        Console.WriteLine("\r\nReturn type: {0}", hello.ReturnType);

        // ReturnTypeCustomAttributes returns an ICustomeAttributeProvider
        // that can be used to enumerate the custom attributes of the
        // return value. At present, there is no way to set such custom
        // attributes, so the list is empty.
        if (hello.ReturnType == typeof(void))
        {
            Console.WriteLine("The method has no return type.");
        }
        else
        {
            ICustomAttributeProvider caProvider = hello.ReturnTypeCustomAttributes;
            object[] returnAttributes = caProvider.GetCustomAttributes(true);
            if (returnAttributes.Length == 0)
            {
                Console.WriteLine("\r\nThe return type has no custom attributes.");
            }
            else
            {
                Console.WriteLine("\r\nThe return type has the following custom attributes:");
                foreach( object attr in returnAttributes )
                {
                    Console.WriteLine("\t{0}", attr.ToString());
                }
            }
        }

        Console.WriteLine("\r\nToString: {0}", hello.ToString());

        // Display parameter information.
        ParameterInfo[] parameters = hello.GetParameters();
        Console.WriteLine("\r\nParameters: name, type, ParameterAttributes");
        foreach( ParameterInfo p in parameters )
        {
            Console.WriteLine("\t{0}, {1}, {2}", 
                p.Name, p.ParameterType, p.Attributes);
        }
    }
}

/* This code example produces the following output:

Use the delegate to execute the dynamic method:

Hello, World!
Invoking delegate hi("Hello, World!", 42) returned: 42

Hi, Mom!
Invoking delegate hi("Hi, Mom!", 5280) returned: 5280

Use the Invoke method to execute the dynamic method:

Hello, World!
hello.Invoke returned: 42

 ----- Display information about the dynamic method -----

Method Attributes: PrivateScope, Public, Static

Calling convention: Standard

DeclaringType is always null for dynamic methods.

This method contains verifiable code. (InitLocals = True)

Module: CommonLanguageRuntimeLibrary

Name: Hello

ReflectedType is null.

Method has no return parameter.

Return type: System.Int32

The return type has no custom attributes.

ToString: Int32 Hello(System.String, Int32)

Parameters: name, type, ParameterAttributes
        message, System.String, In
        valueToReturn, System.Int32, In
 */

System.Object
   System.Reflection.MemberInfo
     System.Reflection.MethodBase
       System.Reflection.MethodInfo
        System.Reflection.Emit.DynamicMethod
Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

Windows 98, Windows Server 2000 SP4, Windows Millennium Edition, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition

The Microsoft .NET Framework 3.0 is supported on Windows Vista, Microsoft Windows XP SP2, and Windows Server 2003 SP1.

.NET Framework

Supported in: 3.0, 2.0
Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback

Community Additions

ADD
Show:
© 2014 Microsoft. All rights reserved.