Ler en inglés

Compartir por


EventInfo.AddEventHandler(Object, Delegate) Método

Definición

Agrega un controlador de eventos a un origen de evento.

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

Parámetros

target
Object

Origen del evento.

handler
Delegate

Encapsula el método o métodos que se invocarán cuando el parámetro de destino provoque el evento.

Implementaciones

Excepciones

El evento no posee un descriptor de acceso add público.

No se puede usar el controlador que se pasó.

El autor de la llamada no tiene permiso para acceder al miembro.

Nota: En .NET para aplicaciones de la Tienda Windows o la Biblioteca de clases portable, detecte la excepción de clase base, MemberAccessException, en su lugar.

El parámetro target es null y el evento no es estático.

O bien

EventInfo no se ha declarado en el destino.

Nota: En .NET para aplicaciones de la Tienda Windows o la biblioteca de clases portable, detecte Exception en su lugar.

Ejemplos

En el ejemplo siguiente se crea una instancia de la System.Timers.Timer clase , se crea un controlador de eventos mediante un ensamblado dinámico y se enlaza el controlador de eventos dinámicos. Todas las acciones se realizan mediante el enlace en tiempo de demora.

La Timer instancia se almacena en una variable de tipo Objecty todo el código que tiene acceso a Timer lo hace en tiempo de ejecución. En el ejemplo se usa el Type.GetEvent método para obtener el Elapsed evento y la EventHandlerType propiedad para obtener el tipo de delegado para el evento.

En el ejemplo se obtiene un MethodInfo para el Invoke método del tipo delegado y se obtiene la firma del delegado de la MethodInfo instancia. A continuación, el ejemplo crea un ensamblado dinámico con un módulo que contiene un único tipo denominado Handler y proporciona al tipo un static método (Shared método en Visual Basic) denominado DynamicHandler que controla el evento.

Una vez creado el tipo dinámico, el ejemplo obtiene un MethodInfo para el método terminado y lo usa para crear una instancia de delegado. Esta instancia se pasa al AddEventHandler método para enlazar el evento. A continuación, el programa se pausa para permitir que se genere el evento.

C#
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.
*/

Comentarios

Este método intenta agregar un delegado para sincronizar el evento en el objeto de destino.

Cada vez que el parámetro de destino genera el evento, se invoca el método o los métodos encapsulados por el controlador.

Puede usar el AddEventHandler método al cargar un tipo después de que el programa ya esté compilado, cuando no es posible usar la sintaxis de C# += o las palabras clave y Handles Visual Basic WithEvents para enlazar el evento.

Se aplica a

Produto Versións
.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, 10
.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

Consulte también