Export (0) Print
Expand All

DynamicMethod Constructor (String, Type, Type[], Boolean)

Initializes an anonymously hosted dynamic method, specifying the method name, return type, parameter types, and whether just-in-time (JIT) visibility checks should be skipped for types and members accessed by the Microsoft intermediate language (MSIL) of the dynamic method.

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

public DynamicMethod(
	string name,
	Type returnType,
	Type[] parameterTypes,
	bool restrictedSkipVisibility
)

Parameters

name
Type: System.String

The name of the dynamic method. This can be a zero-length string, but it cannot be null.

returnType
Type: System.Type

A Type object that specifies the return type of the dynamic method, or null if the method has no return type.

parameterTypes
Type: System.Type[]

An array of Type objects specifying the types of the parameters of the dynamic method, or null if the method has no parameters.

restrictedSkipVisibility
Type: System.Boolean

true to skip JIT visibility checks on types and members accessed by the MSIL of the dynamic method, with this restriction: the trust level of the assemblies that contain those types and members must be equal to or less than the trust level of the call stack that emits the dynamic method; otherwise, false.

ExceptionCondition
ArgumentException

An element of parameterTypes is null or Void.

ArgumentNullException

name is null.

NotSupportedException

returnType is a type for which Type.IsByRef returns true.

The dynamic method that is created by this constructor is associated with an anonymous assembly instead of an existing type or module. The anonymous assembly exists only to provide a sandbox environment for dynamic methods, that is, to isolate them from other code. This environment makes it safe for the dynamic method to be emitted and executed by partially trusted code.

Anonymously hosted dynamic methods do not have automatic access to any types or members that are private, protected, or internal (Friend in Visual Basic). This is different from dynamic methods that are associated with an existing type or module, which have access to hidden members in their associated scope.

Specify true for restrictedSkipVisibility if your dynamic method has to access types or members that are private, protected, or internal. This gives the dynamic method restricted access to these members. That is, the members can be accessed only if the following conditions are met:

  • The target members belong to an assembly that has a level of trust equal to or lower than the call stack that emits the dynamic method.

  • The call stack that emits the dynamic method is granted ReflectionPermission with the ReflectionPermissionFlag.RestrictedMemberAccess flag. This is always true when the code is executed with full trust. For partially trusted code, it is true only if the host explicitly grants the permission.

    Important noteImportant Note:

    If the permission has not been granted, a security exception is thrown when CreateDelegate is called or when the dynamic method is invoked, not when this constructor is called. No special permissions are required to emit the dynamic method.

For example, a dynamic method that is created with restrictedSkipVisibility set to true can access a private member of any assembly on the call stack if the call stack has been granted restricted member access. If the dynamic method is created with partially trusted code on the call stack, it cannot access a private member of a type in a .NET Framework assembly, because such assemblies are fully trusted. 

If restrictedSkipVisibility is false, JIT visibility checks are enforced. The code in the dynamic method has access to public methods of public classes, and exceptions are thrown if it tries to access types or members that are private, protected, or internal.

When an anonymously hosted dynamic method is constructed, the call stack of the emitting assembly is included. When the method is invoked, the permissions of the emitting call stack are used instead of the permissions of the actual caller. Thus, the dynamic method cannot execute at a higher level of privilege than that of the assembly that emitted it, even if it is passed to and executed by an assembly that has a higher trust level.

This constructor specifies the method attributes MethodAttributes.Public and MethodAttributes.Static, and the calling convention CallingConventions.Standard.

NoteNote:

This constructor was introduced in the .NET Framework version 3.5. For more information, see .NET Framework 3.5 Architecture.

The following code example demonstrates the use of the RestrictedMemberAccess flag to allow anonymously hosted dynamic methods to skip JIT visibility checks, but only when the target member is at an equal or lower level of trust than the assembly that emits the code.

The example defines a Worker class that can be marshaled across application domain boundaries. The class has two AccessPrivateMethod method overloads that emit and execute dynamic methods. The first overload emits a dynamic method that calls the private PrivateMethod method of the Worker class, and it can emit the dynamic method with or without JIT visibility checks. The second overload emits a dynamic method that accesses an internal property (Friend property in Visual Basic) of the String class.

The example uses a helper method to get the Internet grant set from security policy, and then creates an application domain, using the AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) method overload to specify that all code that executes in the domain uses this grant set. The example creates an instance of the Worker class in the application domain, and executes the AccessPrivateMethod method two times.

  • The first time the AccessPrivateMethod method is executed, JIT visibility checks are enforced. The dynamic method fails when it is invoked, because JIT visibility checks prevent it from accessing the private method.

  • The second time the AccessPrivateMethod method is executed, JIT visibility checks are skipped. The dynamic method fails when it is compiled, because the Internet grant set does not grant sufficient permissions to skip visibility checks.

The example uses a helper method to get the Internet grant set, and adds ReflectionPermission with ReflectionPermissionFlag.RestrictedMemberAccess to the grant set. The example then creates a second domain, specifying that all code that executes in the domain is granted the permissions in the new grant set. The example creates an instance of the Worker class in the new application domain, and executes both overloads of the AccessPrivateMethod method.

  • The first overload of the AccessPrivateMethod method is executed, and JIT visibility checks are skipped. The dynamic method compiles and executes successfully, because the assembly that emits the code is the same as the assembly that contains the private method. Therefore, the trust levels are equal. If the application that contains the Worker class had several assemblies, the same process would succeed for any one of those assemblies, because they would all be at the same trust level.

  • The second overload of the AccessPrivateMethod method is executed, and again JIT visibility checks are skipped. This time the dynamic method fails when it is compiled, because it tries to access the internal FirstChar property of the String class. The assembly that contains the String class is fully trusted. Therefore, it is at a higher level of trust than the assembly that emits the code.

This comparison shows how ReflectionPermissionFlag.RestrictedMemberAccess enables partially trusted code to skip visibility checks for other partially trusted code without compromising the security of trusted code.

NoteNote:

If you build this code example in Visual Studio, you must change the name of the class to include the default namespace, which is the name of the project. For example, if the project is "AnonymouslyHosted", the class name must be "AnonymouslyHosted.Worker".

using System;
using System.Reflection.Emit;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
using System.Collections;
using System.Diagnostics;

// This code example works properly only if it is run from a fully  
// trusted location, such as your local computer. 

// Delegates used to execute the dynamic methods. 
// 
public delegate void Test(Worker w);
public delegate char Test2(String instance);

// The Worker class must inherit MarshalByRefObject so that its public  
// methods can be invoked across application domain boundaries. 
// 
public class Worker : MarshalByRefObject
{
    private void PrivateMethod()
    {
        Console.WriteLine("Worker.PrivateMethod()");
    }

    // This overload of AccessPrivateMethod emits a dynamic method and 
    // specifies whether to skip JIT visiblity checks. It creates a  
    // delegate for the method and invokes the delegate. The dynamic  
    // method calls a private method of the Worker class. 
    public void AccessPrivateMethod(bool restrictedSkipVisibility) 
    {
        // Create an unnamed dynamic method that has no return type, 
        // takes one parameter of type Worker, and optionally skips JIT 
        // visiblity checks.
        DynamicMethod meth = new DynamicMethod(
            "", 
            null, 
            new Type[] { typeof(Worker) }, 
            restrictedSkipVisibility);

        // Get a MethodInfo for the private method.
        MethodInfo pvtMeth = typeof(Worker).GetMethod("PrivateMethod",
            BindingFlags.NonPublic | BindingFlags.Instance);

        // Get an ILGenerator and emit a body for the dynamic method.
        ILGenerator il = meth.GetILGenerator();

        // Load the first argument, which is the target instance, onto the 
        // execution stack, call the private method, and return.
        il.Emit(OpCodes.Ldarg_0);
        il.EmitCall(OpCodes.Call, pvtMeth, null);
        il.Emit(OpCodes.Ret);

        // Create a delegate that represents the dynamic method, and  
        // invoke it.  
        try 
        {
            Test t = (Test) meth.CreateDelegate(typeof(Test));
            try 
            {
                t(this);
            }
            catch (Exception ex) 
            {
                Console.WriteLine("{0} was thrown when the delegate was invoked.", 
                    ex.GetType().Name);
            }
        } 
        catch (Exception ex) 
        {
            Console.WriteLine("{0} was thrown when the delegate was compiled.", 
                ex.GetType().Name);
        }
    }

    // This overload of AccessPrivateMethod emits a dynamic method that takes 
    // a string and returns the first character, using a private field of the  
    // String class. The dynamic method skips JIT visiblity checks. 
    public void AccessPrivateMethod() 
    {
        DynamicMethod meth = new DynamicMethod(
            "", typeof(char), new Type[] { typeof(String) }, true);

        // Get a MethodInfo for the 'get' accessor of the private property.
        PropertyInfo pi = typeof(System.String).GetProperty(
            "FirstChar",
            BindingFlags.NonPublic | BindingFlags.Instance);
        MethodInfo pvtMeth = pi.GetGetMethod(true);

        // Get an ILGenerator and emit a body for the dynamic method.
        ILGenerator il = meth.GetILGenerator();

        // Load the first argument, which is the target string, onto the 
        // execution stack, call the 'get' accessor to put the result onto  
        // the execution stack, and return.
        il.Emit(OpCodes.Ldarg_0);
        il.EmitCall(OpCodes.Call, pvtMeth, null);
        il.Emit(OpCodes.Ret);

        // Create a delegate that represents the dynamic method, and  
        // invoke it.  
        try 
        {
            Test2 t = (Test2) meth.CreateDelegate(typeof(Test2));
            char first = t("Hello, World!");
            Console.WriteLine("{0} is the first character.", first);
        } 
        catch (Exception ex) 
        {
            Console.WriteLine("{0} was thrown when the delegate was compiled.", 
                ex.GetType().Name);
        }
    }


    // The entry point for the code example. 
    static void Main()
    {
        // Get the display name of the executing assembly, to use when 
        // creating objects to run code in application domains.
        String asmName = Assembly.GetExecutingAssembly().FullName;

        // Create evidence for a partially trusted location and a setup object 
        // that specifies the current directory for the application directory.
        Object[] zoneEvidence = { new Zone(SecurityZone.Internet) };
        Evidence internetZone = new Evidence(zoneEvidence, zoneEvidence);
        AppDomainSetup adSetup = new AppDomainSetup();
        adSetup.ApplicationBase = ".";

        // Retrieve the Internet grant set from system policy, and create a 
        // an Internet application in which all code that executes is granted 
        // the permissions of an application run from the Internet.
        PermissionSet internetSet = GetNamedPermissionSet("Internet");
        AppDomain ad = AppDomain.CreateDomain("ChildDomain1", 
                                              internetZone, 
                                              adSetup, 
                                              internetSet, 
                                              null);

        // Create an instance of the Worker class in the partially trusted  
        // domain. Note: If you build this code example in Visual Studio,  
        // you must change the name of the class to include the default  
        // namespace, which is the project name. For example, if the project 
        // is "AnonymouslyHosted", the class is "AnonymouslyHosted.Worker".
        Worker w = (Worker) ad.CreateInstanceAndUnwrap(asmName, "Worker");

        // Emit and invoke a dynamic method that calls a private method 
        // of Worker, with JIT visibility checks enforced. The call fails  
        // when the delegate is invoked.
        w.AccessPrivateMethod(false);

        // Emit and invoke a dynamic method that calls a private method 
        // of Worker, skipping JIT visibility checks. The call fails when 
        // the method is compiled.
        w.AccessPrivateMethod(true);


        // Unload the application domain. Now create a grant set composed  
        // of the permissions granted to an Internet application plus 
        // RestrictedMemberAccess, and use it to create an application 
        // domain in which partially trusted code can call private members, 
        // as long as the trust level of those members is equal to or lower 
        // than the trust level of the partially trusted code. 
        AppDomain.Unload(ad);
        internetSet = GetNamedPermissionSet("Internet");
        internetSet.SetPermission(
            new ReflectionPermission(
                ReflectionPermissionFlag.RestrictedMemberAccess));
        ad = AppDomain.CreateDomain("ChildDomain2", 
                                    internetZone, 
                                    adSetup, 
                                    internetSet, 
                                    null);

        // Create an instance of the Worker class in the partially trusted  
        // domain. 
        w = (Worker) ad.CreateInstanceAndUnwrap(asmName, "Worker");

        // Again, emit and invoke a dynamic method that calls a private method 
        // of Worker, skipping JIT visibility checks. This time compilation  
        // succeeds because of the grant for RestrictedMemberAccess.
        w.AccessPrivateMethod(true);

        // Finally, emit and invoke a dynamic method that calls an internal  
        // method of the String class. The call fails, because the trust level 
        // of the assembly that contains String is higher than the trust level 
        // of the assembly that emits the dynamic method.
        w.AccessPrivateMethod();
    }


    // This method retrieves a named permission set from security policy. 
    // The return value is the intersection of all permission sets with the 
    // given name, from all policy levels, or an empty permission set if the 
    // name is not found. 
    private static PermissionSet GetNamedPermissionSet(string name)
    {
        if (String.IsNullOrEmpty(name))
            throw new ArgumentException("name", "Cannot search for a permission set without a name.");

        bool foundName = false;
        PermissionSet setIntersection = new PermissionSet(PermissionState.Unrestricted);

        // Search all policy levels.
        IEnumerator levelEnumerator = SecurityManager.PolicyHierarchy();
        while (levelEnumerator.MoveNext())
        {
            PolicyLevel level = levelEnumerator.Current as PolicyLevel;
            Debug.Assert(level != null);

            // If this policy level has a named permission set with the  
            // specified name, intersect it with previous levels.
            PermissionSet levelSet = level.GetNamedPermissionSet(name);
            if (levelSet != null)
            {
                foundName = true;
                setIntersection = setIntersection.Intersect(levelSet);

                // Intersect() returns null for an empty set. If this occurs 
                // at any point, the named permission set is empty. 
                if (setIntersection == null)
                    return new PermissionSet(PermissionState.None);
            }
        }

        if (!foundName)
            setIntersection = new PermissionSet(PermissionState.None);

        return setIntersection;
    }
}

/* This code example produces the following output:

MethodAccessException was thrown when the delegate was invoked.
MethodAccessException was thrown when the delegate was compiled.
Worker.PrivateMethod()
MethodAccessException was thrown when the delegate was compiled.
 */

Windows 7, Windows Vista, Windows XP SP2, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003

The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

.NET Framework

Supported in: 3.5 SP1, 3.0 SP1, 2.0 SP1

Community Additions

ADD
Show:
© 2014 Microsoft