Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subscribe to an event with Reflection

I have a very simple class :

class Trace
{
    void WriteTrace()
    {
        Console.WriteLine("Trace !");
    }
}

I want this class subscribes to an event, for example the load event of a form control. The control and event are define dynamically so I want to use reflection to do this I'm trying something like that :

In my class Trace I have this method :

public void SubscribeEvent (Control control)
{
        if (type.IsAssignableFrom(control.GetType()))
        {
            Trace test = this;
            MethodInfo method = typeof(Trace).GetMethod("WriteTrace");

            // Subscribe to the event
            EventInfo eventInfo = control.GetType().GetEvent("Load"); // We suppose control is a form 
            Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, control, method); // ERROR : Error binding to target method

        }
    }
}

There is an error on the last line : Error binding to target method. What's wrong in my snippet ?

Thank you !

EDIT : Ok, there is no more error but when the event "Load" is raised from the Form, the method WriteTrace is not called (I have put a breakpoint but there is not reached). Why ?

Sorry for the edit, it works very fine :)

like image 948
Florian Avatar asked Nov 05 '10 09:11

Florian


2 Answers

With a few changes, I was able to execute your sample.

Firstly, the method on Trace must have a different signature to correspond with the EventHandler type:

public class Trace
{
    public void WriteTrace(object sender, EventArgs e)
    {
        Console.WriteLine("Trace !");
    }
}

Next, a few changes were made to the SubscribeEvent:

public void SubscribeEvent(Control control)
{
    if (typeof(Control).IsAssignableFrom(control.GetType()))
    {
        Trace test = this;
        MethodInfo method = typeof(Trace).GetMethod("WriteTrace");

        EventInfo eventInfo = control.GetType().GetEvent("Load");

        // Create the delegate on the test class because that's where the
        // method is. This corresponds with `new EventHandler(test.WriteTrace)`.
        Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, test, method);
        // Assign the eventhandler. This corresponds with `control.Load += ...`.
        eventInfo.AddEventHandler(control, handler);
    }
}

I hope this helps.

like image 53
Pieter van Ginkel Avatar answered Oct 16 '22 09:10

Pieter van Ginkel


Your first issue is that Trace.WriteTrace method signature does not match the Form.Load event handler syntax

Try this:

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

Also, your call to CreateDelegate needs to pass the trace object, not the control object:

Trace test = this;
MethodInfo method = typeof(Trace).GetMethod("WriteTrace");

// Subscribe to the event
EventInfo eventInfo = control.GetType().GetEvent("Load"); // We suppose control is a form 

Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, method); // ERROR : Error binding to target method
eventInfo.AddEventHandler(control, handler);
like image 29
Mark Heath Avatar answered Oct 16 '22 09:10

Mark Heath