在.NET中调用匹配多个接口的泛型方法?

时间:2014-05-08 21:59:16

标签: c# .net vb.net generics interface

如果控件与多个接口匹配,我有一个通用的扩展方法。我可以直接在支持两个接口的控件上调用此方法......

Public Function DisplayValue(Of T As {IChoiceControl, IDataSourceControl})(ByVal vctl As T) As String
End Function

Dim pctl As CustomControl = ... //implements above interfaces
Dim pstrDisplayed As String = pctl.DisplayValue() // works

...但是如何构建一个我确定匹配两个接口的对象,以便我可以调用该方法?

Dim pobj As Object = ...
If TypeOf pobj Is IChoiceControl AndAlso TypeOf pobj Is IDataSourceControl Then
    pstrDisplayed = CType(pobj, ?).DisplayValue()
End If

编辑:

定义复合界面(完全如图所示)可以正常工作。感谢。

Public Interface IChoiceDataSourceControl
    Inherits IChoiceControl, IDataSourceControl 
End Interface

If TypeOf pobj Is IChoiceDataSourceControl Then
    pstrDisplayed = CType(pobj, IChoiceDataSourceControl).DisplayValue()
End If

2 个答案:

答案 0 :(得分:2)

  1. 在C#中,您可以使用dynamic,但是您必须放弃用户友好的扩展方法类似实例的调用:

    MyExtensionClass.DisplayValue((dynamic)pobj)
    

    不幸的是,VB.NET中没有dynamic(除非你使用Option Strict Off,这使Object表现得像dynamic)。

  2. 您可以创建包装器:

    Class Wrapper
        Implements IChoiceControl
        Implements IDataSourceControl
    
        Private _choiceControl As IChoiceControl
        Private _dataSource As IDataSourceControl
    
        Public Sub New(obj As Object)
            _choiceControl = CType(obj, IChoiceControl)
            _dataSource = CType(obj, IDataSourceControl)
        End Sub
    
        '' Delegate all IChoiceControl methods to _choiceControl
        '' and IDataSourceControl methods to _dataSource
    End Class
    

    并使用它:

    Dim both As New Both()
    Dim bothAsObject = CType(both, Object)
    Dim wrappedBothAsObject = New Wrapper(bothAsObject)
    wrappedBothAsObject.DisplayValue()
    
  3. 或者您可以创建另一个实现IChoiceControlIDataSourceControl的接口,实现它并将其用作扩展方法的通用约束。

答案 1 :(得分:0)

定义一个从两个接口继承的接口并使你的扩展方法where子句引用它可能更简单:

Public Interface IChoosableDataSourceableThinger 
    Inherits IChoiceControl, IDataSourceControl 
    Public Function DisplayValue As String
End Interface

扩展名:

Public Function DisplayValue(Of T As IChoosableDataSourceableThinger)(ByVal vctl As T) As String

演员:

If TypeOf pobj Is IChoosableDataSourceableThinger Then
    pstrDisplayed = CType(pobj, IChoosableDataSourceableThinger).DisplayValue()
End If