.NET Framework Class Library
EventInfo..::.AddEventHandler Method

Adds an event handler to an event source.

Namespace:  System.Reflection
Assembly:  mscorlib (in mscorlib.dll)
Syntax

Visual Basic (Declaration)
Public Sub AddEventHandler ( _
    target As Object, _
    handler As Delegate _
)
Visual Basic (Usage)
Dim instance As EventInfo
Dim target As Object
Dim handler As [Delegate]

instance.AddEventHandler(target, handler)
C#
public void AddEventHandler(
    Object target,
    Delegate handler
)
Visual C++
public:
virtual void AddEventHandler(
    Object^ target, 
    Delegate^ handler
) sealed
JScript
public final function AddEventHandler(
    target : Object, 
    handler : Delegate
)

Parameters

target
Type: System..::.Object
The event source.
handler
Type: System..::.Delegate
Encapsulates a method or methods to be invoked when the event is raised by the target.

Implements

_EventInfo..::.AddEventHandler(Object, Delegate)
Exceptions

ExceptionCondition
InvalidOperationException

The event does not have a public add accessor.

ArgumentException

The handler that was passed in cannot be used.

MethodAccessException

The caller does not have access permission to the member.

TargetException

The target parameter is nullNothingnullptra null reference (Nothing in Visual Basic) and the event is not static.

-or-

The EventInfo is not declared on the target.

Remarks

This method attempts to add a delegate to synchronize the event on the target object.

Each time the event is raised by the target parameter, the method or methods encapsulated by the handler will be invoked.

Examples

The following code example shows how to load an assembly, create an instance of a type from the assembly, create an event handler using a dynamic assembly, and hook up the dynamic event handler. All actions are performed using late binding.

The code example loads System.dll and creates an instance of the System.Timers..::.Timer class. The example uses the Type..::.GetEvent method to get the Elapsed event, and the EventHandlerType property to get the delegate type for the event.

The code example gets a MethodInfo for the Invoke method of the delegate type, and from the MethodInfo obtains the signature of the delegate. The code example then creates a dynamic assembly with one module containing a single type named Handler, and gives the type a static method (Shared method in Visual Basic) named DynamicHandler that will be used to handle the event.

After the dynamic type is created, the code example gets a MethodInfo for the finished method and uses it to create a delegate instance. This instance is passed to the AddEventHandler method to hook up the event. The program then pauses to allow the event to be raised.

Visual Basic
' New example (user feedback bug 23592) GlennHa 1/4/06
Imports System
Imports System.Reflection
Imports System.Reflection.Emit

Public Class Example

    ' The type used for this code example is the System.Timers.Timer 
    ' class. The Timer object is stored in a variable of type object,
    ' and all code that accesses the Timer does so late-bound. This
    ' is because the scenario in which you might use the AddEVentHander
    ' method is when you load the type after the program is already
    ' compiled, when it is not possible to use the Visual Basic
    ' AddHandler syntax to hook up the event. (Note that there is no 
    ' "Imports" statement for the System.Timers namespace.)
    '
    Private Shared timer As Object

    Public Shared Sub Main() 
        ' Get the assembly that contains the Timer type (Sytem.dll). 
        ' The following code uses the fact that System.dll has the
        ' same public key as mscorlib.dll to construct a string
        ' representing the full assembly name. 
        Dim fullName As String = ""
        For Each assem As [Assembly] In AppDomain.CurrentDomain.GetAssemblies()
            If assem.GetName().Name = "mscorlib" Then
                fullName = assem.FullName
            End If
        Next
        Dim sys As [Assembly] = [Assembly].Load("System" & fullName.Substring(fullName.IndexOf(",")))

        ' Get a Type object representing the Timer type.
        Dim t As Type = sys.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. (In the .NET Framework version 
        ' 2.0 you can 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 = AppDomain.CurrentDomain.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 code 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#
// New example (user feedback bug 23592) GlennHa 1/4/06
using System;
using System.Reflection;
using System.Reflection.Emit;

public class Example
{
    // The type used for this code example is the System.Timers.Timer 
    // class. The Timer object is stored in a variable of type object,
    // and all code that accesses the Timer does so late-bound. This
    // is because the scenario in which you might use the AddEVentHander
    // method is when you load the type after the program is already
    // compiled, when it is not possible to use the C# += syntax to
    // hook up the event. (Note that there is no "using" statement
    // for the System.Timers namespace.)
    //
    private static object timer;

    public static void Main()
    {
        // Get the assembly that contains the Timer type (Sytem.dll). 
        // The following code uses the fact that System.dll has the
        // same public key as mscorlib.dll to construct a string
        // representing the full assembly name. 
        string fullName = "";
        foreach (Assembly assem in AppDomain.CurrentDomain.GetAssemblies())
        {
            if (assem.GetName().Name == "mscorlib")
            {
                fullName = assem.FullName;
            }
        }
        Assembly sys = Assembly.Load("System" + fullName.Substring(fullName.IndexOf(",")));

        // Get a Type object representing the Timer type.
        Type t = sys.GetType("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];
        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. (In the .NET Framework version 
        // 2.0 you can use 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 = AppDomain.CurrentDomain.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.
        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 code 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.
 */
Visual C++
// New example (user feedback bug 23592) GlennHa 1/4/06
using namespace System;
using namespace System::Reflection;
using namespace System::Reflection::Emit;

void main()
{
    // The type used for this code example is the System::Timers::Timer 
    // class. The Timer object is stored in a variable of type object,
    // and all code that accesses the Timer does so late-bound. This
    // is because the scenario in which you might use the AddEVentHander
    // method is when you load the type after the program is already
    // compiled, when it is not possible to use the normal syntax to
    // hook up the event. (Note that there is no "using" statement
    // for the System::Timers namespace.)
    //
    Object^ timer;

    // Get the assembly that contains the Timer type (Sytem.dll). 
    // The following code uses the fact that System.dll has the
    // same public key as mscorlib.dll to construct a string
    // representing the full assembly name. 
    String^ fullName = "";
    for each (Assembly^ assem in AppDomain::CurrentDomain->GetAssemblies())
    {
        if (assem->GetName()->Name == "mscorlib")
        {
            fullName = assem->FullName;
        }
    }
    Assembly^ sys = Assembly::Load("System" + fullName->Substring(fullName->IndexOf(",")));

    // Get a Type object representing the Timer type.
    Type^ t = sys->GetType("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");
    array<ParameterInfo^>^ parms = invokeMethod->GetParameters();
    array<Type^>^ parmTypes = gcnew array<Type^>(parms->Length);
    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. (In the .NET Framework version 
    // 2.0 you can use dynamic methods, which are simpler 
    // because there is no need to create an assembly, module,
    // or type.)
    AssemblyName^ aName = gcnew AssemblyName();
    aName->Name = "DynamicTypes";
    AssemblyBuilder^ ab = AppDomain::CurrentDomain->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.
    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, nullptr, timer, gcnew array<Object^> { 1000 });
    t->InvokeMember("Enabled", BindingFlags::SetProperty, nullptr, timer, gcnew array<Object^> { true });

    Console::WriteLine("Press the Enter key to end the program.");
    Console::ReadLine();

    GC::KeepAlive(timer);
}
/* This code 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.
 */
.NET Framework Security

Platforms

Windows 7, Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98, Windows CE, Windows Mobile for Smartphone, Windows Mobile for Pocket PC, Xbox 360, Zune

The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.
Version Information

.NET Framework

Supported in: 3.5, 3.0, 2.0, 1.1, 1.0

.NET Compact Framework

Supported in: 3.5, 2.0, 1.0

XNA Framework

Supported in: 3.0, 2.0, 1.0
See Also

Reference

Tags :


Page view tracker