在回答之前,我确实有两句话:
- 我同意 Joel 的观点,即通用解决方案会简单得多,但如果没有更多上下文,我会假设您确实需要反思
- 为什么要使用 FormatterServices.GetUninitializedObject()?这不会调用 Table 对象的构造函数。我猜你实际上是想在这里使用 Activator.CreateInstance()。
现在,谈谈手头的问题。您遇到了 .Net 中缺乏对协方差(和逆变)的支持。赋值语句永远不会起作用,也没有反射:
' does not compile (with Option Strict On)
Dim t as Table(Of Object) = New Table(Of Product)
原因是类型实际上不同。虽然 Product 继承自 Object,但这并不意味着 Table(Of Product) 不继承自 Table(Of Object)。
.Net 4 实际上确实支持泛型协变,但仅支持泛型接口和委托类型。通过使用 'out' 关键字注释泛型类型,您可以将其标记为泛型协变。例如,IEnumerable 泛型接口声明如下所示:
IEnumerable(Of Out T)
这意味着现在可以执行以下操作:
Dim mylist As IEnumerable(Of Object) = new List<Product>()
因此可以安全地将 IEnumerable(Of Product) 的列表分配给 IEnumerable(Of Object) 类型的变量。
Here's an explanation of co- and contravariance in VB.Net
所以,你可以做的是为通用表定义一个接口:
Interface ITable(Of Out T)
End Interface
然后你可以在你的通用 Table 类中实现这个接口:
Class Table(Of T)
Implements ITable(Of T)
End Class
那么这将起作用:
Function CreateTable(ByVal t As Type) As ITable(Of Object)
Dim result As ITable(Of Object)
Dim type = GetType(Table(Of )).MakeGenericType(t)
result = FormatterServices.GetUninitializedObject(type)
Return result
End Function
当然,如果可能,最好使用 IEnumerable(Of T) 而不是 ITable(Of T)。