EventInfo.AddEventHandler(Object, Delegate) Metoda
Definicja
Ważne
Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed wydaniem. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Dodaje program obsługi zdarzeń do źródła zdarzeń.
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)
Parametry
- target
- Object
Źródło zdarzenia.
- handler
- Delegate
Hermetyzuje metodę lub metody, które mają być wywoływane, gdy zdarzenie jest wywoływane przez obiekt docelowy.
Implementuje
Wyjątki
Zdarzenie nie ma publicznego add
dostępu.
Nie można użyć procedury obsługi, która została przekazana.
Obiekt wywołujący nie ma uprawnień dostępu do członka.
Uwaga: na platformie .NET dla aplikacji ze Sklepu Windows lub biblioteki klas przenośnych przechwyć wyjątek klasy bazowej , MemberAccessExceptionzamiast tego.
Parametr target
to null
i zdarzenie nie jest statyczne.
-lub-
Obiekt EventInfo nie jest zadeklarowany w obiekcie docelowym.
Uwaga: w programie .NET dla aplikacji ze Sklepu Windows lub w bibliotece klas przenośnych przechwyć Exception zamiast tego.
Przykłady
Poniższy przykład tworzy wystąpienie System.Timers.Timer klasy, tworzy procedurę obsługi zdarzeń przy użyciu zestawu dynamicznego i podłącza dynamiczną procedurę obsługi zdarzeń. Wszystkie akcje są wykonywane przy użyciu późnego powiązania.
Wystąpienie Timer jest przechowywane w zmiennej typu Object, a cały kod, który uzyskuje dostęp do obiektu Timer , odbywa się tak późno. W przykładzie użyto Type.GetEvent metody , aby pobrać Elapsed zdarzenie, oraz EventHandlerType właściwość w celu pobrania typu delegata dla zdarzenia.
Przykład pobiera MethodInfo element dla Invoke
metody typu delegata i uzyskuje podpis delegata MethodInfo z wystąpienia. Następnie przykład tworzy zestaw dynamiczny z jednym modułem zawierającym jeden typ o nazwie Handler
i nadaje typowi metodę (Shared
metodę static
w Visual Basic) o nazwie DynamicHandler
, która obsługuje zdarzenie.
Po utworzeniu typu dynamicznego przykład pobiera MethodInfo element dla gotowej metody i używa go do utworzenia wystąpienia delegata. To wystąpienie jest przekazywane do AddEventHandler metody w celu podłączenia zdarzenia. Następnie program wstrzymuje, aby umożliwić wywoływanie zdarzenia.
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.
Uwagi
Ta metoda próbuje dodać delegata w celu zsynchronizowania zdarzenia w obiekcie docelowym.
Za każdym razem, gdy zdarzenie jest wywoływane przez parametr docelowy, metoda lub metody hermetyzowane przez program obsługi są wywoływane.
Możesz użyć AddEventHandler
metody podczas ładowania typu po skompilowaniu programu, gdy nie można użyć składni języka C# += lub języka Visual Basic WithEvents
i Handles
słów kluczowych, aby podłączyć zdarzenie.