AddEventHandler使用反射

ped*_*des 20 .net c# reflection events

我有这段代码不起作用:

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);
}
Run Code Online (Sandbox Code Playgroud)

Event CardInserted存在于另一个DLL文件中,对象"o"加载OK.委托处理程序具有效果后的值.我只能解雇这个事件.

Dar*_*rov 35

以下是演示如何使用反射附加事件的示例:

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());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我对代码的唯一顾虑是`Func <>`委托不太适合事件.如果您对事件有多个订阅,则只有其中一个实际生成返回值,这可能导致应用程序的非确定性行为. (3认同)

Jon*_*eet 20

这是一个简短但完整的例子,它确实有效:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,当你说"我只能点火事件"时,你究竟是什么意思?你并不打算自己举办活动 - 这取决于活动发布者.您实际呈现给我们的所有代码是否都有效?如果是这样,似乎没有添加问题的事件处理程序.

你能提供更多信息吗?


Mar*_*ell 7

当你说它不起作用时......会发生什么?没有?例外?

思考:

  • 事件和处理程序都是公开的吗?如果没有,您需要将适当BindingFlags的传递给GetEvent/ GetMethodcalls.
  • 处理程序的签名是否匹配?

这是一个工作示例(注意我使用的是静态处理程序,因此为null 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");
    }
}
Run Code Online (Sandbox Code Playgroud)