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
存取子。
無法使用傳入的處理常式。
呼叫端無權存取該成員。
注意:在 適用於 Windows 市集應用程式的 .NET 或 可攜式類別庫中,改為攔截基類例外狀況 MemberAccessException。
target
參數是 null
且事件不是靜態的。
-或-
未在目標上宣告 EventInfo。
注意:在 適用於 Windows 市集應用程式的 .NET 或 可攜式類別庫中,改為攔截 Exception 。
範例
下列範例會建立 類別的 System.Timers.Timer 實例、使用動態元件建立事件處理程式,並鏈接動態事件處理程式。 所有動作都會使用晚期系結來執行。
Timer實例會儲存在 類型的Object變數中,而且所有存取 Timer 的程式代碼都會進行晚期系結。 此範例會 Type.GetEvent 使用 方法來取得 Elapsed 事件,而 EventHandlerType 屬性則會取得事件的委派類型。
此範例會取得MethodInfoInvoke
委派型別方法的 ,並從 實例取得委派的MethodInfo簽章。 然後,此範例會建立一個包含名為 Handler
之單一類型的模組的動態元件,並在Visual Basic中Shared
提供static
方法 (方法) 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
方法。