【问题标题】:Calling a generic method in .NET that matches multiple interfaces? [duplicate]在 .NET 中调用匹配多个接口的泛型方法? [复制]
【发布时间】:2014-06-26 12:38:45
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案1】:
    1. 在 C# 中,您可以使用 dynamic,但您必须放弃用户友好的扩展方法 instance-like 调用:

      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 的接口,实现它并将其用作扩展方法的通用约束。

    【讨论】:

    • “很遗憾,VB.NET 中没有dynamic”——有,不是吗?这就是您使用Option Strict OffObject 的工作原理。 dynamic 将它带到 C# 时,VB.NET 已经拥有它很长时间了。还是 C# 添加了 VB.NET 所缺少的东西?
    • @hvd 我已经更新了我的答案。但是,我不建议任何人转Option String Off :)
    • 嗯,可以对单个模块用单个方法关闭,这样项目的其余部分就可以保留Option Strict On。像这样使用,我有时发现它很有用。
    【解决方案2】:

    定义一个从两个接口继承的接口并让你的扩展方法 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
    

    【讨论】:

    • 但是你必须确保实现这两个接口的所有类都实现了IChoosableDataSourceableThinger。否则,它将不起作用(这不是鸭子打字)。
    • @MarcinJuraszek 我知道 - 我也看到了你的答案,因为我发布了我的答案,所以我赞成你的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-13
    • 1970-01-01
    • 2011-03-14
    • 2014-12-15
    • 1970-01-01
    • 2016-12-14
    相关资源
    最近更新 更多