EventInfo.AddEventHandler(Object, Delegate) Método
Definição
Importante
Algumas informações se referem a produtos de pré-lançamento que podem ser substancialmente modificados antes do lançamento. A Microsoft não oferece garantias, expressas ou implícitas, das informações aqui fornecidas.
Adiciona um manipulador de eventos à origem de um evento.
public:
virtual void AddEventHandler(System::Object ^ target, Delegate ^ handler);
public virtual void AddEventHandler (object target, Delegate handler);
public virtual void AddEventHandler (object? target, Delegate? handler);
public void AddEventHandler (object target, Delegate handler);
abstract member AddEventHandler : obj * Delegate -> unit
override this.AddEventHandler : obj * Delegate -> unit
Public Overridable Sub AddEventHandler (target As Object, handler As Delegate)
Public Sub AddEventHandler (target As Object, handler As Delegate)
Parâmetros
- target
- Object
A fonte do evento.
- handler
- Delegate
Encapsula um ou mais métodos a serem invocados quando o evento é gerado pelo destino.
Implementações
Exceções
O evento não tem um acessador add
público.
O manipulador passado não pode ser usado.
O chamador não tem permissão de acesso ao membro.
Observação: no .NET para aplicativos da Windows Store ou na Biblioteca de Classes Portátil, capture a exceção de classe base, MemberAccessException, em vez disso.
O parâmetro target
é null
e o evento não é estático.
- ou -
O EventInfo não está declarado no destino.
Observação: no .NET para aplicativos da Windows Store ou na Biblioteca de Classes Portátil, capture Exception em vez disso.
Exemplos
O exemplo a seguir cria uma instância da System.Timers.Timer classe , cria um manipulador de eventos usando um assembly dinâmico e conecta o manipulador de eventos dinâmicos. Todas as ações são executadas usando associação tardia.
A Timer instância é armazenada em uma variável do tipo Objecte todo o código que acessa o Timer faz isso com limite tardio. O exemplo usa o Type.GetEvent método para obter o Elapsed evento e a EventHandlerType propriedade para obter o tipo delegado para o evento.
O exemplo obtém um MethodInfo para o Invoke
método do tipo delegado e obtém a assinatura do delegado da MethodInfo instância. Em seguida, o exemplo cria um assembly dinâmico com um módulo que contém um único tipo chamado Handler
e fornece ao tipo um static
método (Shared
método no Visual Basic) chamado DynamicHandler
que manipula o evento.
Depois que o tipo dinâmico é criado, o exemplo obtém um MethodInfo para o método concluído e o usa para criar uma instância delegada. Essa instância é passada para o AddEventHandler método para conectar o evento. Em seguida, o programa pausa para permitir que o evento seja acionado.
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.
*/
Imports System.Reflection
Imports System.Reflection.Emit
Public Class Example
Private Shared timer As Object
Public Shared Sub Main()
' Get the Timer type.
Dim t As Type = GetType(System.Timers.Timer)
' Create an instance of the Timer type.
timer = Activator.CreateInstance(t)
' Use reflection to get the Elapsed event.
Dim eInfo As EventInfo = 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.
'
Dim handlerType As Type = eInfo.EventHandlerType
Dim invokeMethod As MethodInfo = handlerType.GetMethod("Invoke")
Dim parms As ParameterInfo() = invokeMethod.GetParameters()
'
' Note that in Visual Basic you must dimension the array one
' unit smaller than the source array in order to get an array
' of the same size. This is because Visual Basic adds an extra
' element to every array, for ease of use.
'
Dim parmTypes(parms.Length - 1) As Type
Dim i As Integer
For i = 0 To parms.Length - 1
parmTypes(i) = parms(i).ParameterType
Next i
' 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 alsso use dynamic methods,
' which are simpler because there is no need to create an
' assembly, module, or type.)
Dim aName As New AssemblyName()
aName.Name = "DynamicTypes"
Dim ab As AssemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Run)
Dim mb As ModuleBuilder = ab.DefineDynamicModule(aName.Name)
Dim tb As TypeBuilder = mb.DefineType("Handler", TypeAttributes.Class Or TypeAttributes.Public)
' Create the method that will handle the event. The name
' is not important. The method is Shared ("static" in
' reflection), because there is no reason to create an
' instance of the dynamic type "Handler".
'
' The parameter types and return type of the method are
' the same as those of the delegate's Invoke method,
' captured earlier.
Dim handler As MethodBuilder = tb.DefineMethod("DynamicHandler", MethodAttributes.Public Or MethodAttributes.Static, invokeMethod.ReturnType, parmTypes)
' Generate code to handle the event. In this case, the
' handler simply prints a text string to the console.
'
Dim il As ILGenerator = 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.
Dim finished As Type = tb.CreateType()
Dim eventHandler As MethodInfo = finished.GetMethod("DynamicHandler")
' Use the MethodInfo to create a delegate of the correct
' type, and call the AddEventHandler method to hook up
' the event.
Dim d As [Delegate] = [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, Nothing, timer, New [Object]() {1000})
t.InvokeMember("Enabled", BindingFlags.SetProperty, Nothing, timer, New [Object]() {True})
Console.WriteLine("Press the Enter key to end the program.")
Console.ReadLine()
End Sub
End Class
' 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.
Comentários
Esse método tenta adicionar um delegado para sincronizar o evento no objeto de destino.
Sempre que o evento é gerado pelo parâmetro de destino, o método ou os métodos encapsulados pelo manipulador são invocados.
Você pode usar o AddEventHandler
método quando carregar um tipo depois que o programa já estiver compilado, quando não for possível usar a sintaxe C# += ou o Visual Basic WithEvents
e Handles
palavras-chave para conectar o evento.