Title: Howto invoke an event via reflection
Date: 2008-08-29 23:14:53


Why this article ? Because of this note found on the MSDN's `EventInfo`
page:

> EventInfo is not intended to be used to raise events. An object
> raises events as dictated by its internal state.

Let's try to raise an event with reflection ... Firstly, let's search,
but not in `GetEvent`, in `GetField` : [Type.GetField(String,
BindingFlags)](http://msdn.microsoft.com/en-us/library/4ek9c21e.aspx)
`String` is the name of the field to get and
[BindingFlags](http://msdn.microsoft.com/en-us/library/system.reflection.bindingflags.aspx)
a bitmask of serarching flags. Note: To use reflexion, use
"System.Reflection" Let's try a `GetField`:

    :::csharp
    FieldInfo my_event_FieldInfo = this.GetType().GetField("my_event",
                                                           BindingFlags.NonPublic
                                                           | BindingFlags.Instance);

Yeah! It's not `null`! we have now the `FieldInfo` of our event. What to
do now ? in a `FieldInfo`, we do not have something like "Fire the event",
huh But what about "GetValue" ? The "Value" of a "FieldInfo" is the
field, so the Value of an event's `FieldInfo` isn't the Event?
[FieldInfo.GetValue(object)](http://msdn.microsoft.com/en-us/library/system.reflection.fieldinfo.getvalue.aspx) let's try:

    :::csharp
    object my_event_by_reflection = my_event_FieldInfo.GetValue(this);

Is `null` ... ): Ohhhh but, while not registered, an event is `null`... so,
let's try adding a handler... Is not null!! Yeah, so we have our event
by reflection now.

Note for those who just said "Why giving an object to `GetValue`? And
why giving 'this'":

- Take a look at the first "this.getType()"
- Deduce that it ask the Object to give you its Type, an Object knows
its Type.
- Note that a Type can't know its Objects...
- Finally to get a Field of your Object, you ask the Type to give it
  or your Object, giving a reference to your Object, here : 'this';


Now, we have an object, which is the event to call, but, how to call
it? By reflection? but... where to search? TRICK: Put a
breakpoint just after the `GetValue`, when breaked, add a watch on
`my_event_by_reflection.GetType()` and browse it... try
`my_event_by_reflection.GetType().GetFields()`... nothing... try
`my_event_by_reflection.GetType().GetMethods()`... browse it... OH
?  What is `Invoke` ?

    :::csharp
    var my_event_invoke = my_event_type.GetMethod("Invoke");

Searching how to call the Invoke... by reflection? Invoking invoke?

Let's try:

    :::csharp
    my_event_invoke.Invoke(my_event_by_reflection, new object[] {this, new EventArgs()} );

Invoke take the instance of this type, so the object where GetType where
called, and in second parameter an array of object to be given as
parameter to the method called, we have to give an object and an
eventArgs. It Works ! here the full working source code:

    :::csharp
    using System.Reflection;

    class Cage_en_metal
    {
        public event EventHandler ecraser;

        public Cage_en_metal()
        {
            ecraser += new EventHandler(Libellule_ecraser);
            fireEvent("ecraser", new EventArgs());
        }

        void Libellule_ecraser(object sender, EventArgs e)
        {
            Console.WriteLine("Splatch !");
        }

        void fireEvent(string handler, EventArgs eventArgs)
        {
            var eventInfo = this.GetType().GetField(handler,
                                            BindingFlags.Instance
                            | BindingFlags.NonPublic);
            if (eventInfo != null)
            {
                var event_member = eventInfo.GetValue(this);
            // Note : If event_member is null, nobody registered to the event, you can't call it.
                if (event_member != null)
                    event_member.GetType().GetMethod("Invoke").Invoke(event_member, new object[] { this, eventArgs });
            }
        }
    }
