我想知道是否有人对解决以下设计问题有好的建议或模式。我有一组命令类,最抽象的级别是ICommand接口。执行ICommand的RunCommand()函数的结果是一个对象。不同的命令将具有不同的结果类型,因此这是一个适当的抽象。
在构建层次结构时,使用泛型会更加方便。我创建了一个Generic.ICommand(Of TResult)接口。
有一些通用的样板代码,例如Run、TryRun、BeginRun、BeginTryRun等,我希望所有命令都能使用 - 因此我创建了一个BaseCommand类,它提供了所有这些内容,并实现了非泛型ICommand接口。但是,BaseCommand并不知道如何实际执行任何操作,因此所有这些命令最终都会调用一个受保护的抽象函数InternalRunCommand。这一切都很顺利。
现在我想创建该类的通用版本:BaseCommand(Of T)。它继承自BaseCommand,并实现了通用的ICommand(Of T)接口。这很有效,但现在存在一个差异:InternalRunCommand。
在非泛型版本中,InternalRunCommand返回一个对象。在我的通用BaseCommand(Of T)类中,我想用返回类型为T的通用版本重载它。不幸的是,VB.NET/C#编译器不允许您提供一个方法的重载,其中唯一的区别是返回类型。
由于这是一个受保护的函数,它对整个API的影响并不大,但我仍然感到烦恼,因为我没有一个美观的解决方案来解决这个架构问题。
目前,我已经在BaseCommand(Of T)类中重写了非泛型InternalRunCommand,以便调用一个新的受保护的抽象OnRunCommand函数,该函数具有相同的参数但返回类型为T。InternalRunCommand也已声明为不可重载。这可能是我能接受的最接近的解决方案 - 但我想知道是否还有更好的想法? :)
编辑:如请求所示,我已包含了代码的简化副本,以便您可以更好地理解问题:
在构建层次结构时,使用泛型会更加方便。我创建了一个Generic.ICommand(Of TResult)接口。
有一些通用的样板代码,例如Run、TryRun、BeginRun、BeginTryRun等,我希望所有命令都能使用 - 因此我创建了一个BaseCommand类,它提供了所有这些内容,并实现了非泛型ICommand接口。但是,BaseCommand并不知道如何实际执行任何操作,因此所有这些命令最终都会调用一个受保护的抽象函数InternalRunCommand。这一切都很顺利。
现在我想创建该类的通用版本:BaseCommand(Of T)。它继承自BaseCommand,并实现了通用的ICommand(Of T)接口。这很有效,但现在存在一个差异:InternalRunCommand。
在非泛型版本中,InternalRunCommand返回一个对象。在我的通用BaseCommand(Of T)类中,我想用返回类型为T的通用版本重载它。不幸的是,VB.NET/C#编译器不允许您提供一个方法的重载,其中唯一的区别是返回类型。
由于这是一个受保护的函数,它对整个API的影响并不大,但我仍然感到烦恼,因为我没有一个美观的解决方案来解决这个架构问题。
目前,我已经在BaseCommand(Of T)类中重写了非泛型InternalRunCommand,以便调用一个新的受保护的抽象OnRunCommand函数,该函数具有相同的参数但返回类型为T。InternalRunCommand也已声明为不可重载。这可能是我能接受的最接近的解决方案 - 但我想知道是否还有更好的想法? :)
编辑:如请求所示,我已包含了代码的简化副本,以便您可以更好地理解问题:
Public Interface ICommand
Property Name as String
Property Description As String
Property ResultType as Type
Function RunCommand(target as Device) As Object
Function TryRunCommand(target as Device, Byref result as Object) AS Boolean
Function BeginRunCommand(target as Device) as Task(Of Object)
Function BeginTryRunCommand(target as Device) As Task(of Boolean)
End Interface
Namespace Generic
Public Interface ICommand(Of TResult)
Function RunCommand(target as Device) as T
Function BeginRunCommand(target as Device) As Task(Of T)
End Interface
End Namespace
Public MustInherit Class BaseCommand
Implements ICommand
Public Function RunCommand(target as Device) As Object Implements ICommand.RunCommand
Return InternalRunCommand(device)
End Function
Public Function BeginRunCommand(target as Device) As Task(of Object) Implements ICommand.BeginRunCommand
Return Task(Of Object).Factory.StartNew( Function() InternalRunCommand(target))
End Function
' Other boiler plate code goes here'
Protected MustOverride Function InternalRunCommand(target as Device) As Object
End Class
Namespace Generic
Public Class BaseCommand(Of TResult)
Inherits BaseCommand
Implements ICommand(Of TResult)
Public Function BeginRunCommand(target as Device) As Task(of TResult) Implements ICommand(Of TResult).BeginRunCommand
Return Task(Of TResult).Factory.StartNew( Function() OnRunCommand(target))
End Function
Protected NotOverridable Overrides Function InternalRunCommand(target as Device) As Object
' Re-route to the generic version'
Return OnRunCommand(device)
End Function
Protected MustOverride Function OnRunCommand(target as Device) As T
End Class
Object
版本从泛型中继承,而不是相反?其次,另一个可能要考虑的事情是使用Shadows
来用更具体的版本替换泛型中的Object
版本。 - Craig