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

时间:2019-04-04 13:11:44

标签: vb.net event-handling

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

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

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

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

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

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

任何建议都值得赞赏。

2 个答案:

答案 0 :(得分:4)

是的,您可以使用反射按名称找到该方法,但我不建议这样做。通常为{ "USR_ID":"10", "ID":"1" , "ORDER_DATE":"12-03-2018", "CASE_NUMBER":"554" } 命令提供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 而不是将方法名称硬编码为字符串文字,只是为了使其更安全):

NameOf

答案 1 :(得分:0)

您想要代码将字符串映射到方法引用。我对语法的了解不再100%清楚,但看起来可能像这样:

Dim actionMap As Dictionary(Of string, Action(Of Object, EventArgs))
actionMap.Add("DrawLogo", AddressOf DrawLogo)
actionmap.Add("PublishDrawing", AddressOf PublishDrawing)

然后For Each循环可以使用这样的字典:

For Each oCommand As MyCommand In oCommands
    Dim oCommandDef As Inventor.CommandDefinition = InventorApp.CommandDefinitions.Add(oCommand.InternalDefinitionName, oCommand.DisplayName)
    InventorApp.ToolbarButtons.Add(oCommandDef)

    AddHandler oCommandDef.OnExecute, actionMap(oCommand.HandlerSubName)
Next

当我在这里时,我将添加从VB6 / VBScript到.Net的迁移,Microsoft更改了其VB样式指南。现在,他们不再推荐像o这样的匈牙利疣,而是根据.Net更强烈地使用类型和更好的工具支持的方式,建议反对。前缀只是不添加它们以前使用的值,现在您可以只写oCommand,而不是command,这样可读性更强。