避免参数 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