在不知道通用类型的情况下转换为通用类型

时间:2019-12-17 08:17:20

标签: vb.net generics

我有一个使用泛型类型的接口(ValueControl),还有另一个使用该接口实例的类(ValueControlHandler)。现在,当我在ValueControlHandler中创建CreateHandler时,我需要传递通用类型。现在TCtrl很“容易”(我只是使用ValueControl,但我不知道如何设置TVal

Public Interface ValueControl(Of T)
    ReadOnly Property Value As T
End Interface

Public Interface CtrlChanges
    Function HasChanges() As Boolean
End Interface

Friend Class ValueControlHandler(Of TCtrl As ValueControl(Of TVal), TVal)
    Implements CtrlChanges
    ....
End Class

Private Function DummyCreateHandler(Of TVal)(ByVal ctrl as ValueControl(Of TVal)) As CtrlChanges
    Return New ValueControlHandler(Of ValueControl(Of TVal), TVal)(ctrl)
End Function

Private Function CreateHandler(ByVal ctrl As Object) As CtrlChanges
    If TypeOf ctrl Is ValueControl(Of ValueControl(Of ???), ???) Then  ' <!--- Problem here
        Return New ValueControlHandler(Of ValueControl(Of ???), ???)(ctrl)  ' <!--- Problem here
    ElseIf Typeof ctrl Is AnotherType Then
        Return New AnotherCtrlChanges(....)
    Else
        Return Nothing
    End If
End Function

棘手的是,我对CtrlChanges部分感兴趣的时候,甚至不需要知道类型。是删除通用名称并将其默认设置为Object的唯一解决方案吗?我也使用DummyCreateHandler进行了尝试,但是后来我仍然不知道如何检查类型,并且对于第二次调用并没有太大帮助。

如果有帮助,这里是ValueControlHandler中的完整课程:

Friend Class ValueControlHandler(Of TCtrl As ValueControl(Of TVal), TVal)
    Implements CtrlChanges

    Protected ReadOnly Ctrl As TCtrl

    Protected ReadOnly Val As TVal

    Public Sub New(ByVal Ctrl As TCtrl)
        Me.Ctrl = Ctrl
        Me.Val = CurrentValue
    End Sub

    Public ReadOnly Property CurrentValue As TVal
        Get
            Return Ctrl.Value
        End Get
    End Property

    Public Overridable Function HasChanges() As Boolean Implements CtrlChanges.HasChanges
        Return CType(CurrentValue, Object) <> Val
    End Function
End Class

2 个答案:

答案 0 :(得分:0)

您是否考虑过将工厂方法作为ValueControl的一部分? (附带说明,接口上的“ I”前缀是标准约定)

(请注意,我的VB.NET有点生锈,尽管您有错字,希望您能了解这种方法的意图)

Public Interface IValueControl(Of T)
   ReadOnly Property Value As T
   ValueControlHandler(Of T) CreateValueControlHandler(ctrl As IValueControl(Of T))
End Interface

然后每个控件都可以生成自己的ValueControlHandler

Public Class MyControl Inherits Textbox Implements IValueControl(Of String)

   Public Function ValueControlHandler(Of T) CreateValueControlHandler()

      Return New ValueControlHandler(Of MyControl, String)(Me)

   End Fucntion

End Class

答案 1 :(得分:0)

CreateHandler可以将要参数化的类型作为参数。然后,您将执行以下操作:

Private Function CreateHandler(ByVal ctrl As Object, ByVal TVal as Type) As CtrlChanges

    '...
    Dim genericValueControlType = GetType(ValueControl(Of )) 'Intentionally blank, the type is the unspecialized generic type.
    Dim specificValueControlType = genericValueControlType.MakeGenericType(TVal)

    'Untested, might need to be Is instead of =
    If ctrl.GetType() = specificValueControlType Then
        Dim genericHandlerType = GetType(ValueControlHandler(Of ) 'Untested, might need a comma to indicate two missing type params
        Dim specificHandlerType = genericHandlerType.MakeGenericType(specificValueControlType, TVal)
        Dim retval = specificHandlerType.GetConstructor({}).Invoke({})
        Return CType(retval, CtrlChanges)
    End If
End Function

根据工厂例程中的详细程度,您还可以考虑基于反射和/或一个或多个约定进行构建。不幸的是,.NET中缺少静态接口方法,这意味着约定是跨接口的不同实现调用逻辑Shared例程的唯一方法(即在逻辑上创建Shared无论如何都可以使用实例化方法,以便可以将其放在接口上;我已经完成了这两项工作,但都不是完全令人满意的。)