[英]Cast to a generic type without knowing generic type
I have an interface ( ValueControl
) using a generic type and have another class ( ValueControlHandler
) which uses an instance of that interface.我有一个使用泛型类型的接口(
ValueControl
),还有另一个使用该接口实例的类( ValueControlHandler
)。 Now when I create ValueControlHandler
in CreateHandler
I need to pass the generic types.现在,当我在
CreateHandler
创建ValueControlHandler
,我需要传递泛型类型。 Now TCtrl
is "easy" (I just use ValueControl
but I don't know how to set TVal
.现在
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
The tricky part is, that I don't even need to know the type as I'm interested in the CtrlChanges
part.棘手的部分是,我什至不需要知道类型,因为我对
CtrlChanges
部分感兴趣。 Is the only solution to drop the generics and default to Object
?是删除泛型并默认为
Object
的唯一解决方案吗? I also tried it with DummyCreateHandler
but then I still don't know how to check the type and it didn't really help much for the second call.我也用
DummyCreateHandler
尝试过,但后来我仍然不知道如何检查类型,而且它对第二次调用并没有太大帮助。
Here is the complete class from ValueControlHandler
if this helps:如果有帮助,这里是
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
Have you considered including a factory method as part of ValueControl
?您是否考虑过将工厂方法作为
ValueControl
一部分? (Side note, the "I" prefix on interfaces is a standard convention) (旁注,接口上的“I”前缀是标准约定)
(Note, my VB.NET is a bit rusty, hopefully you can get the intent of this approach despite my typos): (注意,我的 VB.NET 有点生疏,希望你能理解这种方法的意图,尽管我有错别字):
Public Interface IValueControl(Of T)
ReadOnly Property Value As T
ValueControlHandler(Of T) CreateValueControlHandler(ctrl As IValueControl(Of T))
End Interface
Then each control can generate it's own ValueControlHandler
:然后每个控件可以生成它自己的
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
CreateHandler
could take the type to parameterize on as an argument. CreateHandler
可以将要参数化的类型作为参数。 Then, you would do something like this:然后,你会做这样的事情:
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
Depending on the level of detail in your factory routine, you could also consider building up based on reflection and/or one or more conventions.根据工厂例程中的详细程度,您还可以考虑基于反射和/或一种或多种约定进行构建。 Unfortunately, the lack of static interface methods in .NET means that convention is the only way to invoke a logically-
Shared
routine across different implementations of an interface (that, or making something that is logically Shared
a per-instance method anyway so that it can be put on an interface; I've done both and neither is completely satisfactory).不幸的是,.NET 中缺少静态接口方法意味着约定是在接口的不同实现之间调用逻辑
Shared
例程的唯一方法(即,或者使逻辑上Shared
的某些东西成为每个实例的方法,以便它可以放在一个界面上;我两个都做过,但都不完全令人满意)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.