EventInfo.AddEventHandler(Object, Delegate) Metodo

Definizione

Aggiunge un gestore eventi a un'origine eventi.

public virtual void AddEventHandler (object target, Delegate handler);
public virtual void AddEventHandler (object? target, Delegate? handler);
public void AddEventHandler (object target, Delegate handler);

Parametri

target
Object

Origine evento.

handler
Delegate

Incapsula uno o più metodi da richiamare se l'evento viene generato dalla destinazione.

Implementazioni

Eccezioni

L'evento non ha una funzione di accesso add pubblica.

Non è possibile usare il gestore passato.

Il chiamante non ha l'autorizzazione necessaria per accedere al membro.

Nota: in .NET per le app di Windows Store o la libreria di classi portabili, rilevare invece l'eccezione della classe di base, , MemberAccessException.

Il parametro target è null e l'evento non è statico.

-oppure-

L'oggetto EventInfo non è dichiarato nella destinazione.

Nota: in .NET per le app di Windows Store o la libreria di classi portabile, rilevareException invece.

Esempio

Nell'esempio seguente viene creata un'istanza System.Timers.Timer della classe, viene creato un gestore eventi usando un assembly dinamico e viene collegato il gestore eventi dinamico. Tutte le azioni vengono eseguite usando l'associazione tardiva.

L'istanza Timer viene archiviata in una variabile di tipo Objecte tutto il Timer codice che accede a tale oggetto associato in ritardo. Nell'esempio viene usato il Type.GetEvent metodo per ottenere l'evento Elapsed e la EventHandlerType proprietà per ottenere il tipo delegato per l'evento.

L'esempio ottiene un MethodInfo oggetto per il Invoke metodo del tipo delegato e ottiene la firma del delegato dall'istanza MethodInfo . L'esempio crea quindi un assembly dinamico con un modulo contenente un singolo tipo denominato Handler e assegna al tipo un static metodo (Shared metodo in Visual Basic) denominato DynamicHandler che gestisce l'evento.

Dopo aver creato il tipo dinamico, l'esempio ottiene un MethodInfo oggetto per il metodo completato e lo usa per creare un'istanza delegato. Questa istanza viene passata al metodo per collegare l'evento AddEventHandler . Il programma viene quindi sospeso per consentire la generazione dell'evento.

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

public class Example
{
    private static object? timer;

    public static void Main()
    {
        // Get the Timer type.
        Type t = typeof(System.Timers.Timer);
        // Create an instance of the Timer type.
        timer = Activator.CreateInstance(t);

        // Use reflection to get the Elapsed event.
        EventInfo? eInfo = t.GetEvent("Elapsed");

        // In order to create a method to handle the Elapsed event,
        // it is necessary to know the signature of the delegate
        // used to raise the event. Reflection.Emit can then be
        // used to construct a dynamic class with a static method
        // that has the correct signature.

        // Get the event handler type of the Elapsed event. This is
        // a delegate type, so it has an Invoke method that has
        // the same signature as the delegate. The following code
        // creates an array of Type objects that represent the
        // parameter types of the Invoke method.
        //
        Type? handlerType = eInfo?.EventHandlerType;
        MethodInfo? invokeMethod = handlerType?.GetMethod("Invoke");
        ParameterInfo[]? parms = invokeMethod?.GetParameters();
        Type[] parmTypes = new Type[parms?.Length ?? 0];
        for (int i = 0; i < parms?.Length; i++)
        {
            parmTypes[i] = parms[i].ParameterType;
        }

        // Use Reflection.Emit to create a dynamic assembly that
        // will be run but not saved. An assembly must have at
        // least one module, which in this case contains a single
        // type. The only purpose of this type is to contain the
        // event handler method. (You can use also dynamic methods,
        // which are simpler because there is no need to create an
        // assembly, module, or type.)
        //
        AssemblyName aName = new AssemblyName();
        aName.Name = "DynamicTypes";
        AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Run);
        ModuleBuilder mb = ab.DefineDynamicModule(aName.Name);
        TypeBuilder tb = mb.DefineType("Handler", TypeAttributes.Class | TypeAttributes.Public);

        // Create the method that will handle the event. The name
        // is not important. The method is static, because there is
        // no reason to create an instance of the dynamic type.
        //
        // The parameter types and return type of the method are
        // the same as those of the delegate's Invoke method,
        // captured earlier.
        MethodBuilder handler = tb.DefineMethod("DynamicHandler",
            MethodAttributes.Public | MethodAttributes.Static,
            invokeMethod?.ReturnType, parmTypes);

        // Generate code to handle the event. In this case, the
        // handler simply prints a text string to the console.
        //
        ILGenerator il = handler.GetILGenerator();
        il.EmitWriteLine("Timer's Elapsed event is raised.");
        il.Emit(OpCodes.Ret);

        // CreateType must be called before the Handler type can
        // be used. In order to create the delegate that will
        // handle the event, a MethodInfo from the finished type
        // is required.
        Type? finished = tb.CreateType();
        MethodInfo? eventHandler = finished?.GetMethod("DynamicHandler");

        // Use the MethodInfo to create a delegate of the correct
        // type, and call the AddEventHandler method to hook up
        // the event.
        if (handlerType is not null && eventHandler is not null)
        {
            Delegate d = Delegate.CreateDelegate(handlerType, eventHandler);
            eInfo?.AddEventHandler(timer, d);
        }

        // Late-bound calls to the Interval and Enabled property
        // are required to enable the timer with a one-second
        // interval.
        t.InvokeMember("Interval", BindingFlags.SetProperty, null, timer, new Object[] { 1000 });
        t.InvokeMember("Enabled", BindingFlags.SetProperty, null, timer, new Object[] { true });

        Console.WriteLine("Press the Enter key to end the program.");
        Console.ReadLine();
    }
}
/* This example produces output similar to the following:

Press the Enter key to end the program.
Timer's Elapsed event is raised.
Timer's Elapsed event is raised.
Timer's Elapsed event is raised.
*/

Commenti

Questo metodo tenta di aggiungere un delegato per sincronizzare l'evento nell'oggetto di destinazione.

Ogni volta che l'evento viene generato dal parametro di destinazione, viene richiamato il metodo o i metodi incapsulati dal gestore.

È possibile usare il AddEventHandler metodo quando si carica un tipo dopo che il programma è già compilato, quando non è possibile usare la sintassi C# += o le parole chiave e Handles Visual Basic WithEvents per collegare l'evento.

Si applica a

Prodotto Versioni
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1
UWP 10.0

Vedi anche