Questa documentazione è stata archiviata e non viene gestita.

Classe DynamicMethod

Aggiornamento: novembre 2007

Definisce e rappresenta un metodo dinamico che può essere compilato, eseguito ed eliminato. I metodi scartati sono disponibili per la procedura di garbage collection.

Spazio dei nomi:  System.Reflection.Emit
Assembly:  mscorlib (in mscorlib.dll)

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

È possibile utilizzare la classe DynamicMethod per generare ed eseguire un metodo in fase di esecuzione, senza l'esigenza di generare un assembly dinamico e un tipo dinamico per contenere il metodo. Il codice eseguibile creato dal compilatore JIT (Just-In-Time) viene recuperato quando si recupera l'oggetto DynamicMethod. I metodi dinamici rappresentano il modo più efficace per generare ed eseguire codice di dimensioni limitate.

Un metodo dinamico può essere contenuto anonimamente o può essere associato logicamente a un modulo o a un tipo.

  • Se il metodo dinamico è contenuto anonimamente, si trova in un assembly fornito dal sistema e pertanto è isolato dall'altro codice. Per impostazione predefinita, non ha accesso a un qualsiasi dato non pubblico. Un metodo dinamico contenuto anonimamente può avere una limitata possibilità di ignorare i controlli di visibilità del compilatore JIT, se gli è stato concesso un oggetto ReflectionPermission con il flag ReflectionPermissionFlag.RestrictedMemberAccess. Il livello di attendibilità dell'assembly ai cui membri non pubblici accede il metodo dinamico deve essere uguale, o un sottoinsieme, del livello di attendibilità dello stack di chiamate che ha generato il metodo dinamico. Per ulteriori informazioni sui metodi dinamici contenuti anonimamente, vedere Procedura dettagliata: emissione di codice in scenari di attendibilità parziale.

  • Se il metodo dinamico viene associato a un modulo specificato, il metodo dinamico risulta globale per tale modulo. Può accedere a tutti i tipi nel modulo e a tutti i membri internal (Friend in Visual Basic) dei tipi. È possibile associare un metodo dinamico a qualsiasi modulo, indipendentemente dal fatto che il modulo sia stato creato, purché possa venire soddisfatta una richiesta per ReflectionPermission con il flag RestrictedMemberAccess, dallo stack di chiamate che include il codice. Se il flag ReflectionPermissionFlag.MemberAccess è incluso nell'autorizzazione, il metodo dinamico può ignorare i controlli di visibilità del compilatore JIT e accedere ai dati privati di tutti i tipi dichiarati all'interno del modulo o in qualsiasi altro modulo in qualsiasi assembly.

    Nota:

    Quando si specifica il modulo al quale è associato un metodo dinamico, tale modulo non deve essere all'interno dell'assembly fornito dal sistema utilizzato per l'hosting anonimo.

  • Se il metodo dinamico è associato a un tipo specificato, ha accesso a tutti i membri privati del tipo, indipendentemente dal livello di accesso Inoltre possono venire ignorati i controlli di visibilità del compilatore JIT. In tal modo il metodo dinamico accede ai dati privati di altri tipi dichiarati nello stesso o in qualsiasi altro modulo. È possibile associare un metodo dinamico a qualsiasi tipo, ma il codice deve disporre di ReflectionPermission con entrambi i flag RestrictedMemberAccess e MemberAccess.

Nella tabella seguente vengono descritti tipi e membri accessibili da un metodo dinamico contenuto anonimamente, con e senza controlli di visibilità di JIT, a seconda se dispone o meno di ReflectionPermission con il flag RestrictedMemberAccess.

 

Senza RestrictedMemberAccess

Con RestrictedMemberAccess

Senza ignorare i controlli di visibilità di JIT

Membri pubblici di tipi pubblici in qualsiasi assembly.

Membri pubblici di tipi pubblici in qualsiasi assembly.

Ignorando i controlli di visibilità di JIT, con restrizioni

Membri pubblici di tipi pubblici in qualsiasi assembly.

Tutti i membri di qualsiasi tipo, solo negli assembly i cui livelli di attendibilità sono uguali o inferiori al livello di attendibilità dell'assembly che ha generato il metodo dinamico.

Nota:

A partire da .NET Framework 2.0 Service Pack 1, la creazione di codice richiedeva ReflectionPermission con il flag ReflectionPermissionFlag.ReflectionEmit. Questa autorizzazione è inclusa per impostazione predefinita nei set di autorizzazioni denominati FullTrust e LocalIntranet, ma non nel set di autorizzazioni Internet. Di conseguenza nelle versioni precedenti di .NET Framework una libreria può essere utilizzata con autorizzazioni Internet solo se è presente un attributo SecurityCriticalAttribute ed esegue un oggetto Assert per ReflectionEmit. Tali librerie richiedono una accurata revisione della sicurezza perché eventuali errori nel codice potrebbero comportare problemi di sicurezza. .NET Framework 2.0 SP1 consente che il codice venga generato in scenari di attendibilità parziale senza emettere alcuna richiesta di sicurezza, perché la generazione di codice non è, per sua natura, un'operazione privilegiata. Ovvero, il codice generato non ha più autorizzazioni dell'assembly che lo genera. Questo consente alle librerie che generano il codice di essere SecurityTransparent ed elimina la necessità di utilizzare un'asserzione di ReflectionEmit, semplificando l'attività di scrittura di una libreria protetta. Per utilizzare questa funzionalità, l'applicazione deve essere indirizzata a .NET Framework versione 3.5. Per ulteriori informazioni, vedere Architettura di .NET Framework 3.5.

Nella tabella seguenti vengono descritti i tipi e i membri accessibili a un metodo dinamico associato con un modulo o con un tipo in un modulo.

 

Associato al modulo

Associato al tipo

Senza ignorare i controlli di visibilità di JIT

Membri pubblici e interni di tipi pubblici, interni e privati nel modulo.

Membri pubblici di tipi pubblici in qualsiasi assembly.

Tutti i membri del tipo associato. Membri pubblici e interni di qualsiasi altro tipo nel modulo.

Membri pubblici di tipi pubblici in qualsiasi assembly.

Ignorando i controlli di visibilità di JIT

Tutti i membri di qualsiasi tipo in qualsiasi assembly.

Tutti i membri di qualsiasi tipo in qualsiasi assembly.

Un metodo dinamico associato a un modulo dispone dell'autorizzazione di tale modulo. Un metodo dinamico associato a un tipo dispone dell'autorizzazione del modulo che contiene tale tipo.

Non è necessario assegnare nomi ai metodi dinamici e ai relativi parametri, ma è possibile specificare nomi per il supporto del debug. Gli attributi personalizzati non sono supportati sui metodi dinamici o nei relativi parametri.

Sebbene i metodi dinamici siano metodi static (metodi Shared in Visual Basic), le regole relaxed per l'associazione di delegati introdotta in .NET Framework 2.0 consentono l'associazione di un metodo dinamico a un oggetto affinché funga da metodo di istanza quando viene chiamato mediante l'istanza del delegato. Un esempio di questa procedura è fornito per l'overload di metodi CreateDelegate(Type, Object).

Nota:

In .NET Framework 2.0, i metodi dinamici non supportano informazioni sui simboli, ovvero nomi della variabile locali e mapping del numero di riga. Questo limite potrebbe venire rimosso dalle versioni future. È possibile utilizzare AssemblyBuilder durante lo sviluppo per semplificare il debug del linguaggio MSIL (Microsoft Intermediate Language) generato e quindi passare ai metodi dinamici durante la distribuzione finale, perché le chiamate ILGenerator sono le stesse in entrambi casi.

Nell'esempio di codice riportato di seguito viene creato un metodo dinamico che accetta due parametri. In questo esempio viene creato il corpo di una funzione semplice che consente la visualizzazione del primo parametro sulla console, mentre il secondo parametro viene utilizzato come valore restituito del metodo. Nell'esempio, viene completato il metodo mediante la creazione di un delegato, viene chiamato il delegato con parametri diversi e infine viene chiamato il metodo dinamico mediante il metodo Invoke.

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
 */


Qualsiasi membro static (Shared in Visual Basic) pubblico di questo tipo è thread-safe. I membri di istanza non sono garantiti come thread-safe.

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

.NET Framework e .NET Compact Framework non supportano tutte le versioni di ciascuna piattaforma. Per un elenco delle versioni supportate, vedere Requisiti di sistema di .NET Framework.

.NET Framework

Supportato in: 3.5, 3.0, 2.0
Mostra: