避免参数 class 上的长 case 语句
Avoiding long case statement on argument class
有一个 class 层级的任务可以由 class A 执行。
在 class A 中有一个很长的 case 语句检查任务 class 并调用相应的处理程序方法。
Class Task
End Class
Class TaskX
Inherits Task
End Class
Class TaskY
Inherits Task
End Class
...
Class A
Public Sub PerformTask(Task As Task)
Select Case Task.GetType
Case GetType(TaskX)
PerformTaskX(CType(Task, TaskX))
Case GetType(TaskY)
PerformTaskY(CType(Task, TaskY))
End Select
End Sub
Private Sub PerformTaskX(Task As TaskX)
End Sub
Private Sub PerformTaskY(Task As TaskY)
End Sub
...
End Class
任务有其各自的参数、验证逻辑等。示例已简化。
我想避免 case 语句,我正在寻找替代解决方案。
一般的想法是将 class 类型映射到 Handler(Of class),它可以像这样以某种方式工作:
Delegate Sub Handler(Task As Task)
Private TypeToHandlerDict As New Dictionary(Of System.Type, Handler) From { _
{GetType(TaskX), AddressOf PerformTaskX}, _
{GetType(TaskY), AddressOf PerformTaskY} _
}
这样我就可以用更优雅的方法替换 PerformTask 方法的内容:
Public Sub PerformTask(Task As Task)
Dim handler As Handler = Nothing
If Not TypeToHandlerDict.TryGetValue(Task.GetType, handler) Then Exit Sub
handler(Task)
End Sub
但是没用。
委托绑定到任务类型,但处理程序方法接受任务子class参数。我正在使用 Option Strict。
我可以重写所有处理程序方法以接受任务对象并执行显式转换,但这同样不够优雅。
有什么建议吗?
谢谢!
更新:感谢@Sehnsucht 的回答,这是解决方案。
Class Task
Public MustOverride Sub Perform(a As A)
End Class
Class TaskX
Inherits Task
Public Overrides Sub Perform(a As A)
a.DoThis()
End Sub
End Class
Class TaskY
Inherits Task
Public Overrides Sub Perform(a As A)
a.DoThat()
End Sub
End Class
...
Class A
Public Sub PerformTask(Task As Task)
Task.Perform(Me)
End Sub
Public Sub DoThis()
End Sub
Public Sub DoThat()
End Sub
...
End Class
所有 PerformTask...
都具有相同的签名,并且由您在 post.
中显示的代表 Handler
强制执行
因此,您应该在 Task
class 中使用默认实现创建一个 Overridable 方法(或者如果 Task class 是 MustInherit,则将该方法标记为 MustOverride),该方法将被其继承者覆盖根据他们的具体情况来完成工作。
Class Task
Public Overridable Sub Perform()
' implementation specific to Task ("default" case)
End Sub
End Class
Class TaskX
Inherits Task
Public Overrides Sub Perform()
' implementation specific to TaskX
' you can call the parent implementation if needed with
MyBase.Perform()
End Sub
End Class
'Usage
Class A
Public Sub PerformTask(task As Task)
task.Perform() ' will call the "right one" according to it's runtime type
End Sub
End Class
有一个 class 层级的任务可以由 class A 执行。
在 class A 中有一个很长的 case 语句检查任务 class 并调用相应的处理程序方法。
Class Task
End Class
Class TaskX
Inherits Task
End Class
Class TaskY
Inherits Task
End Class
...
Class A
Public Sub PerformTask(Task As Task)
Select Case Task.GetType
Case GetType(TaskX)
PerformTaskX(CType(Task, TaskX))
Case GetType(TaskY)
PerformTaskY(CType(Task, TaskY))
End Select
End Sub
Private Sub PerformTaskX(Task As TaskX)
End Sub
Private Sub PerformTaskY(Task As TaskY)
End Sub
...
End Class
任务有其各自的参数、验证逻辑等。示例已简化。
我想避免 case 语句,我正在寻找替代解决方案。
一般的想法是将 class 类型映射到 Handler(Of class),它可以像这样以某种方式工作:
Delegate Sub Handler(Task As Task)
Private TypeToHandlerDict As New Dictionary(Of System.Type, Handler) From { _
{GetType(TaskX), AddressOf PerformTaskX}, _
{GetType(TaskY), AddressOf PerformTaskY} _
}
这样我就可以用更优雅的方法替换 PerformTask 方法的内容:
Public Sub PerformTask(Task As Task)
Dim handler As Handler = Nothing
If Not TypeToHandlerDict.TryGetValue(Task.GetType, handler) Then Exit Sub
handler(Task)
End Sub
但是没用。
委托绑定到任务类型,但处理程序方法接受任务子class参数。我正在使用 Option Strict。 我可以重写所有处理程序方法以接受任务对象并执行显式转换,但这同样不够优雅。
有什么建议吗? 谢谢!
更新:感谢@Sehnsucht 的回答,这是解决方案。
Class Task
Public MustOverride Sub Perform(a As A)
End Class
Class TaskX
Inherits Task
Public Overrides Sub Perform(a As A)
a.DoThis()
End Sub
End Class
Class TaskY
Inherits Task
Public Overrides Sub Perform(a As A)
a.DoThat()
End Sub
End Class
...
Class A
Public Sub PerformTask(Task As Task)
Task.Perform(Me)
End Sub
Public Sub DoThis()
End Sub
Public Sub DoThat()
End Sub
...
End Class
所有 PerformTask...
都具有相同的签名,并且由您在 post.
中显示的代表 Handler
强制执行
因此,您应该在 Task
class 中使用默认实现创建一个 Overridable 方法(或者如果 Task class 是 MustInherit,则将该方法标记为 MustOverride),该方法将被其继承者覆盖根据他们的具体情况来完成工作。
Class Task
Public Overridable Sub Perform()
' implementation specific to Task ("default" case)
End Sub
End Class
Class TaskX
Inherits Task
Public Overrides Sub Perform()
' implementation specific to TaskX
' you can call the parent implementation if needed with
MyBase.Perform()
End Sub
End Class
'Usage
Class A
Public Sub PerformTask(task As Task)
task.Perform() ' will call the "right one" according to it's runtime type
End Sub
End Class