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



我正在为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"之外,还有其他方法可能有效吗?

任何建议不胜感激。

是的,您可以使用反射按名称找到该方法,但我不推荐它。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而不是将方法名称硬编码为字符串文字,只是为了更安全):

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

您希望代码将字符串映射到方法引用。我不再 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,这往往更具可读性。

相关内容

  • 没有找到相关文章

最新更新