Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AddEventHandler using reflection

Tags:

I have this piece of code that does not work:

public CartaoCidadao()
{
    InitializeComponent();

    object o = WebDAV.Classes.SCWatcher.LoadAssembly();
    MethodInfo method = 
        this.GetType().GetMethod("Inserted", 
                                 BindingFlags.NonPublic | BindingFlags.Instance);

    EventInfo eventInfo = o.GetType().GetEvent("CardInserted");
    Type type = eventInfo.EventHandlerType;
    Delegate handler = Delegate.CreateDelegate(type, this , method);

    eventInfo.AddEventHandler(o, handler);
}

void Inserted(string readerName, string cardName)
{
    System.Windows.Forms.MessageBox.Show(readerName);
}

The Event CardInserted exists in another DLL file and object "o" loads OK. The delegate handler has a value after effect. I only can't fire the event.

like image 648
pedrofernandes Avatar asked Jul 13 '09 19:07

pedrofernandes


3 Answers

Here's a sample showing how to attach an event using reflection:

class Program
{
    static void Main(string[] args)
    {
        var p = new Program();
        var eventInfo = p.GetType().GetEvent("TestEvent");
        var methodInfo = p.GetType().GetMethod("TestMethod");
        Delegate handler = 
             Delegate.CreateDelegate(eventInfo.EventHandlerType, 
                                     p, 
                                     methodInfo);
        eventInfo.AddEventHandler(p, handler);

        p.Test();
    }

    public event Func<string> TestEvent;

    public string TestMethod()
    {
        return "Hello World";
    }

    public void Test()
    {
        if (TestEvent != null)
        {
            Console.WriteLine(TestEvent());
        }
    }
}
like image 178
Darin Dimitrov Avatar answered Mar 01 '23 13:03

Darin Dimitrov


Here's a short but complete example which does work:

using System;
using System.Reflection;

class EventPublisher
{
    public event EventHandler TestEvent;

    public void RaiseEvent()
    {
        TestEvent(this, EventArgs.Empty);
    }
}

class Test
{

    void HandleEvent(object sender, EventArgs e)
    {
        Console.WriteLine("HandleEvent called");
    }

    static void Main()
    {
        // Find the handler method
        Test test = new Test();
        EventPublisher publisher = new EventPublisher();
        MethodInfo method = typeof(Test).GetMethod
            ("HandleEvent", BindingFlags.NonPublic | BindingFlags.Instance);

        // Subscribe to the event
        EventInfo eventInfo = typeof(EventPublisher).GetEvent("TestEvent");
        Type type = eventInfo.EventHandlerType;
        Delegate handler = Delegate.CreateDelegate(type, test, method);

        // Raise the event
        eventInfo.AddEventHandler(publisher, handler);
        publisher.RaiseEvent();
    }
}

Now, when you say "I only can't fire event", what exactly do you mean? You're not meant to be able to raise events yourself - it's up to the event publisher to do that. Does all of the code you've actually presented to us work? If so, it seems that it's not adding the event handler that's the problem.

Could you give more information?

like image 37
Jon Skeet Avatar answered Mar 01 '23 14:03

Jon Skeet


When you say it doesn't work... what happens? Nothing? An exception?

Thoughts:

  • are both the event and the handler public? If not, you'll need to pass suitable BindingFlags to the GetEvent / GetMethod calls.
  • does the signature of the handler match?

Here's a working example (note I'm using a static handler, hence the null in Delegate.CreateDelegate):

using System;
using System.Reflection;
class Test
{
    public event EventHandler SomeEvent;
    public void OnSomeEvent()
    {
        if (SomeEvent != null) SomeEvent(this, EventArgs.Empty);
    }
    static void Main()
    {
        Test obj = new Test();
        EventInfo evt = obj.GetType().GetEvent("SomeEvent");
        MethodInfo handler = typeof(Test)
            .GetMethod("MyHandler");
        Delegate del = Delegate.CreateDelegate(
            evt.EventHandlerType, null, handler);
        evt.AddEventHandler(obj, del);

        obj.OnSomeEvent();
    }

    public static void MyHandler(object sender, EventArgs args)
    {
        Console.WriteLine("hi");
    }
}
like image 36
Marc Gravell Avatar answered Mar 01 '23 13:03

Marc Gravell