EventInfo.AddEventHandler(Object, Delegate) Метод
Определение
Важно!
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Добавляет обработчик событий в источник события.
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)
Параметры
- target
- Object
Источник события.
- handler
- Delegate
Инкапсулирует метод или методы, вызываемые при создании события целевым объектом.
Реализации
Исключения
Это событие не поддерживает открытый метод доступа add
.
Переданный обработчик нельзя использовать.
Вызывающий объект не имеет разрешения на доступ к этому элементу.
Примечание. Вместо этого в .NET для приложений Магазина Windows или переносимой библиотеке классов перехватите исключение MemberAccessExceptionбазового класса , .
Параметр target
имеет значение null
, и событие не является статическим.
-или-
Класс EventInfo не объявлен для целевого объекта.
Примечание. Вместо этого в .NET для приложений Магазина Windows или переносимой библиотеке классов выполните перехват Exception .
Примеры
В следующем примере создается экземпляр System.Timers.Timer класса , создается обработчик событий с помощью динамической сборки и подключается обработчик динамических событий. Все действия выполняются с использованием поздней привязки.
Экземпляр Timer хранится в переменной типа Object, и весь код, который обращается к объекту Timer , делает это с поздней привязкой. В примере используется Type.GetEvent метод для получения Elapsed события, а EventHandlerType свойство — для получения типа делегата для события.
Пример получает MethodInfo для Invoke
метода типа делегата и получает сигнатуру делегата из экземпляра MethodInfo . Затем в примере создается динамическая сборка с одним модулем, содержащим один тип с именем Handler
, и предоставляется типу static
метод (Shared
метод в Visual Basic), DynamicHandler
который обрабатывает событие.
После создания динамического типа пример получает MethodInfo для готового метода и использует его для создания экземпляра делегата. Этот экземпляр передается в AddEventHandler метод для подключения события. Затем программа приостанавливается, чтобы разрешить вызов события.
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.
Комментарии
Этот метод пытается добавить делегат для синхронизации события в целевом объекте.
Каждый раз, когда событие вызывается целевым параметром, вызывается метод или методы, инкапсулированные обработчиком.
Метод можно использовать AddEventHandler
при загрузке типа после компиляции программы, когда невозможно использовать синтаксис C# += или ключевые слова Visual Basic WithEvents
и Handles
для подключения события.