EventInfo.AddEventHandler(Object, Delegate) 方法
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
将事件处理程序添加到事件源。
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 for Windows 应用商店应用 或 可移植类库中,请改为捕获基类异常 MemberAccessException。
target
参数为 null
,并且此事件不是静态事件。
或
未在目标上声明 EventInfo。
注意:在 .NET for Windows 应用商店应用 或 可移植类库中,请改为 catch Exception 。
示例
以下示例创建 类的 System.Timers.Timer 实例,使用动态程序集创建事件处理程序,并挂钩动态事件处理程序。 所有操作都使用后期绑定执行。
实例 Timer 存储在 类型 Object为 的变量中,访问 的所有代码 Timer 都是后期绑定的。 该示例使用 Type.GetEvent 方法获取 Elapsed 事件,使用 EventHandlerType 属性获取事件的委托类型。
该示例获取MethodInfoInvoke
委托类型的 方法的 ,并从 实例获取委托的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.
注解
此方法尝试添加委托以同步目标对象上的事件。
每次目标参数引发事件时,都会调用处理程序封装的方法。
在编译程序后加载类型时,如果无法使用 C# += 语法或 Visual Basic WithEvents
和 Handles
关键字来挂钩事件,则可以使用 AddEventHandler
方法。