VB.NET:通过将处理程序函数指定为变量来实现“AddHandler”

DRo*_*oam 3 vb.net event-handling

我正在为 Autodesk Inventor(一个 3D CAD 程序)编写一个插件。该插件向 Inventor 添加了一系列内部命令,并为每个命令创建了一个工具栏按钮。我需要将每个命令的 Execute 事件连接到加载项中的处理程序函数。

我创建了一个“MyCommand”类,其中包含定义命令所需的所有信息。我还创建了一个 List(Of MyCommand) ,其中包含每个命令的定义。最后,我可以遍历每个命令并创建内部 Inventor 命令定义,以及将按钮添加到工具栏。但是,我不知道该怎么做是将命令与其 Handler 函数在 loop 内关联起来。

下面的示例代码说明了我所追求的:

Sub CreateCommands()
    Dim oCommands As New List(Of MyCommand)

    oCommands.Add(New MyCommand("DrawLogoCmd", "Draw Logo", "DrawLogoSub"))
    oCommands.Add(New MyCommand("PublishDrawingCmd", "Publish Drawing", "PublishDrawingSub"))
    ' [Dozens more commands]

    For Each oCommand As MyCommand In oCommands
        ' Code for adding internal command definition and button to Inventor. This is working fine.
        Dim oCommandDef As Inventor.CommandDefinition = InventorApp.CommandDefinitions.Add(oCommand.InternalDefinitionName, oCommand.DisplayName)
        InventorApp.ToolbarButtons.Add(oCommandDef)

        ' Associate command definition with handler function
        ' ===== THIS IS THE LINE I NEED TO FIGURE OUT =====
        AddHandler oCommandDef.OnExecute, AddressOf oCommand.HandlerSubName
    Next
End Sub

Sub DrawLogoSub()
    ' [My add-in's code to draw logo in Inventor]
End Sub

Sub PublishDrawingSub()
    ' [My add-in's code to publish drawing in Inventor]
End Sub

Class MyCommand
    Public InternalDefinitionName As String
    Public DisplayName As String
    Public HandlerSubName As String

    Sub New(InternalDefinitionName As String, DisplayName As String, HandlerSubName As String)
        With Me
            .InternalDefinitionName = InternalDefinitionName
            .DisplayName = DisplayName
            .HandlerSubName = HandlerSubName
        End With
    End Sub
End Class
Run Code Online (Sandbox Code Playgroud)

那么,这可能吗?有什么方法可以使用其名称作为字符串来获取我的函数的“AddressOf”?或者,是否有某种方法可以在 MyCommand 类中存储对函数本身的引用,并将其传递给 AddressOf 运算符?

或者,除了“AddHandler/AddressOf”之外还有其他方法可以使用吗?

任何建议表示赞赏。

Ste*_*art 5

是的,您可以使用反射按名称找到该方法,但我不推荐它。该AddHandler命令通常给出的AddressOf一个方法,但它也可以采取委托,只要它符合事件的签名。所以,除非你有一些需要通过字符串来做,否则我建议你做这样的事情。假设事件匹配普通EventHandler委托:

Sub CreateCommands()
    Dim oCommands As New List(Of MyCommand)

    oCommands.Add(New MyCommand("DrawLogoCmd", "Draw Logo", AddressOf DrawLogo))
    oCommands.Add(New MyCommand("PublishDrawingCmd", "Publish Drawing", AddressOf PublishDrawing))
    ' [Dozens more commands]

    For Each oCommand As MyCommand In oCommands
        ' Code for adding internal command definition and button to Inventor. This is working fine.
        Dim oCommandDef As Inventor.CommandDefinition = InventorApp.CommandDefinitions.Add(oCommand.InternalDefinitionName, oCommand.DisplayName)
        InventorApp.ToolbarButtons.Add(oCommandDef)

        ' Associate command definition with handler function
        AddHandler oCommandDef.OnExecute, oCommand.Handler
    Next
End Sub

Sub DrawLogo(sender As Object, e As EventArgs)
    ' [My add-in's code to draw logo in Inventor]
End Sub

Sub PublishDrawing(sender As Object, e As EventArgs)
    ' [My add-in's code to publish drawing in Inventor]
End Sub

Class MyCommand
    Public InternalDefinitionName As String
    Public DisplayName As String
    Public Handler As EventHandler

    Sub New(InternalDefinitionName As String, DisplayName As String, Handler As EventHandler)
        With Me
            .InternalDefinitionName = InternalDefinitionName
            .DisplayName = DisplayName
            .Handler = Handler
        End With
    End Sub
End Class
Run Code Online (Sandbox Code Playgroud)

如果你真的需要通过字符串来做,你可以使用这样的反射(请注意,我使用NameOf而不是将方法名称硬编码为字符串文字,只是为了使其更安全):

Sub CreateCommands()
    Dim oCommands As New List(Of MyCommand)

    oCommands.Add(New MyCommand("DrawLogoCmd", "Draw Logo", NameOf(DrawLogo)))
    oCommands.Add(New MyCommand("PublishDrawingCmd", "Publish Drawing", NameOf(PublishDrawing)))
    ' [Dozens more commands]

    For Each oCommand As MyCommand In oCommands
        ' Code for adding internal command definition and button to Inventor. This is working fine.
        Dim oCommandDef As Inventor.CommandDefinition = InventorApp.CommandDefinitions.Add(oCommand.InternalDefinitionName, oCommand.DisplayName)
        InventorApp.ToolbarButtons.Add(oCommandDef)

        ' Associate command definition with handler function
        AddHandler oCommandDef.OnExecute, Sub(sender As Object, e As EventArgs) CallMethod(oCommand.Handler)
    Next
End Sub

Private Sub CallMethod(name As String)
    Me.GetType().GetMethod(name).Invoke(Me, Nothing)
End Sub

Sub DrawLogo()
    ' [My add-in's code to draw logo in Inventor]
End Sub

Sub PublishDrawing()
    ' [My add-in's code to publish drawing in Inventor]
End Sub
Run Code Online (Sandbox Code Playgroud)