Подтвердить что ты не робот

AddEventHandler с использованием отражения

У меня есть этот код, который не работает:

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);
}

Событие CardInserted существует в другом DLL файле, а объект "o" загружает OK. Обработчик делегата имеет значение после эффекта. Я не могу запустить это событие.

4b9b3361

Ответ 1

Вот пример, показывающий, как присоединить событие, используя отражение:

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());
        }
    }
}

Ответ 2

Вот короткий, но полный пример, который работает:

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();
    }
}

Теперь, когда вы говорите: "Я только не могу запустить событие", что именно вы имеете в виду? Вы не должны собирать события самостоятельно - это до издателя событий, чтобы сделать это. Весь код, который вы нам действительно представили, работает? Если это так, кажется, что это не добавляет обработчик события, что проблема.

Не могли бы вы предоставить дополнительную информацию?

Ответ 3

Когда вы говорите, что это не работает... что происходит? Ничего? Исключение?

Мысли:

  • являются и событием, и обработчиком общедоступным? Если нет, вам нужно передать подходящий BindingFlags в вызовы GetEvent/GetMethod.
  • Соответствует ли подпись обработчика?

Вот рабочий пример (обратите внимание, что я использую статический обработчик, следовательно, значение 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");
    }
}