如何将事件处理程序分配给EventInfo中已知的事件?

时间:2015-09-02 17:14:07

标签: c# .net vb.net winforms events

我想迭代控件(例如TextBox)支持的所有事件,并以编程方式为每个事件分配相同的诊断事件处理程序。

很明显我不能使用C#+=或VB AddHandler命令。如何为GetType(TextBox).GetEvents()中已知的每个事件分配事件处理程序?

Imports System.Reflection

Public Class Form1

    Public Sub New()
        InitializeComponent()

        For Each ei As EventInfo In GetType(TextBox).GetEvents()
            'AddHandler TextBox1.ei, AddressOf DiagnosticHandler - PLEASE HELP ME HERE
        Next
    End Sub

    Private Sub DiagnosticHandler(sender As Object, e As EventArgs)
        'whatever
    End Sub

End Class

(C#或VB - 无论你喜欢什么。)

2 个答案:

答案 0 :(得分:3)

EventInfo type has AddEventHandler() method完全是出于此目的。

兼容性: .NET 3.5 及更高版本(已测试。)

最小有效代码:

Public Sub New()
    InitializeComponent() ' needed only in Form class
    BindHandlers(TextBox1) ' this is our binding
End Sub

Public Sub BindHandlers(c As Control)
    Dim handler As MethodInfo = Me.GetType().GetMethod(NameOf(DiagnosticEventHandler))
    For Each ei In c.GetType().GetEvents()
        ei.AddEventHandler(c, [Delegate].CreateDelegate(ei.EventHandlerType, handler))
    Next
End Sub

Public Shared Sub DiagnosticEventHandler(sender As Object, e As EventArgs)
    'whatever
End Sub

注意:我只使用Public Shared处理程序方法成功。使用Private和非共享方法,我收到了签名兼容性错误,而我却懒得解决。

那些一直读到这一点的人的奖金:

Public Shared Sub DiagnosticEventHandler(sender As Object, e As EventArgs)
    'heuristic disclosing of method related to event name
    Dim maxAttempts As Integer = 15
    Dim attempt As Integer = 1
    Dim stackTrace As New StackTrace()
    Do While attempt <= maxAttempts
        Dim methodName As String = stackTrace.GetFrame(attempt).GetMethod().Name
        attempt += 1
        If methodName.StartsWith("On") Then
            Debug.Print(String.Join(" > ", stackTrace.GetFrames().Take(attempt).Skip(1).Select(Of String)(Function(sf) sf.GetMethod.Name).Reverse().ToArray()))
            Return
        End If
    Loop
    Debug.Print(String.Join(" > ", stackTrace.GetFrames().Take(maxAttempts).Select(Of String)(Function(sf) sf.GetMethod.Name).Reverse().ToArray()))
End Sub

答案 1 :(得分:1)

以防有人需要它,这里是完成该操作的代码(假设您在表单中有一个名为textBox1的TextBox。)

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        MethodInfo miHandler = typeof(Form1).GetMethod("DiagnosticHandler", BindingFlags.NonPublic | BindingFlags.Instance);

        EventInfo[] events = typeof(TextBox).GetEvents();

        foreach (EventInfo ei in events)
        {
            Type tDelegate = ei.EventHandlerType;
            Delegate d = Delegate.CreateDelegate(tDelegate, this, miHandler);
            MethodInfo addHandler = ei.GetAddMethod();
            Object[] addHandlerArgs = { d };
            addHandler.Invoke(this.textBox1, addHandlerArgs);
        }

    }

    private void DiagnosticHandler(object sender, EventArgs e)
    {
        //whatever
    }
}

更多信息here