存储实现多个接口并从某个基础派生的对象(.net)

时间:2010-12-07 03:58:34

标签: vb.net inheritance interface .net-2.0 covariance

在.net中,可以使用泛型,以便函数可以接受支持一个或多个接口的参数并从基类型派生,即使不存在所有有效参数类型派生的任何单一类型。例如,可以说:

Sub Foo(Of T As {IInterface1, IInterface2, SomeBaseType})(Param as T)

并允许传递SomeBaseType的任何衍生物,它实现了IInterface1和IInterface2。即使SomeBaseType不支持Interface1和Interface2,这也会起作用,并且实现这些接口的类不共享任何也实现它们的共同祖先。

如果在函数退出后不需要将参数保留在任何位置,这将非常方便。不幸的是,我无法找到一种方法来保持传入的参数,以便稍后可以传递给类似的函数,除非使用Reflection。有没有好办法呢?

我能够提出的最接近的是定义一个接口INest(可能不是最好的名字 - 任何人都可以改进吗?)因此:

Interface INest(Of Out T)
    Function Nest() As T
End Interface

对于将与其他接口或基类“约束”结合使用的任何接口,定义一个通用版本,如下所示

Interface IFun1
    ' Any members of the interface go here, e.g. ...'
    Sub DoFun1()
End Interface

Interface IFun1(Of Out T)
    ' This one does nothing but inherit'
    Inherits IFun1, INest(Of T)
End Interface

支持多个接口的类应该声明自己实现泛型接口,并将自身作为类型参数。

Class test123a
    Inherits sampleBase
    Implements IFun1(Of test123a), IFun2(Of test123a), IFun3(Of test123a)
End Class

如果这样做,可以定义一个支持多个约束的函数参数或类变量:

Dim SomeField as IFun1(Of IFun2(Of IFun3(Of sampleBase)))

然后为它分配从sampleBase派生的任何类,它实现了这些接口。 SomeField将实现IFun1; SomeField.Nest将实现IFun2; SomeField.Nest.Nest将实现IFun3。请注意,除了从INest(Of T)继承的通用接口之外,不要求IFun1,IFun2,IFun3或sampleBase共享任何公共派生。还要注意,无论一个类实现了多少个INest派生接口,它只需要定义INest(Of T).Nest的一个实现。

不完全漂亮,但有两件好事:(1)实际上实现必要接口的任何具体类都可以直接分配给上面声明的字段,而不需要进行类型转换; (2)虽然以不同顺序链接类型的字段不是赋值兼容的,但它们可能相互转换。

有没有更好的方法以某种方式存储某些东西,以便它“已知”支持多个接口并从某种基类型派生?鉴于可以以类型安全的方式编写此类代码,如果编译器提供了一些帮助,那么.net 2.0 CLR似乎可能很好地支持这样的事情。不过,我不知道现有编译器有什么特别好的方法。

1 个答案:

答案 0 :(得分:2)

我能想到的最好的方法是创建这个存储的抽象存储和通用实现。例如(原谅我的VB.NET):

MustInherit Class Storage
    Public MustOverride Sub DoSomething()
End Class

Class Storage(Of T As {IInterface1, IInterface2, SomeBaseType})
    Inherits Storage

    Public Overrides Sub DoSomething()
        ' do something with Value.
    End Sub

    Public Value As T
End Class

使用

Dim S As Storage

Sub Foo(Of T As {IInterface1, IInterface2, SomeBaseType})(ByVal Param As T)
    S = New Storage(Of T) With {.Value = Param}
End Sub

Sub UseS()
    S.DoSomething();
End Sub

更新:好的,因为我们可能无法事先确定所有行动:

MustInherit Class Storage
    MustOverride ReadOnly Property SomeBaseType As SomeBaseType
    MustOverride ReadOnly Property IInterface1 As IInterface1
    MustOverride ReadOnly Property IInterface2 As IInterface2
End Class

Class Storage(Of T As {IInterface1, IInterface2, SomeBaseType})
    Inherits Storage

    Public Value As T

    Public Overrides ReadOnly Property IInterface1 As IInterface1
        Get
            Return Value
        End Get
    End Property

    Public Overrides ReadOnly Property IInterface2 As IInterface2
        Get
            Return Value
        End Get
    End Property

    Public Overrides ReadOnly Property SomeBaseType As SomeBaseType
        Get
            Return Value
        End Get
    End Property
End Class