在运行时反射和更改变量类型?

时间:2010-05-26 17:25:56

标签: vb.net reflection types

我正在尝试创建特定类型的对象。我有以下代码,但它失败了,因为它无法将新表对象强制转换为已定义的对象。我需要表来启动IEnumerable类型,所以我不能声明是一个对象。

Public sub getTable(ByVal t as Type)

   Dim table As Table(Of Object)

   Dim tableType As Type = GetType(Table(Of )).MakeGenericType(t)

   table = FormatterServices.GetUninitializedObject(tableType)

End sub 

简而言之 - 有没有办法在运行时更改变量类型? (或者做我正在做的更好的方式)

提前致谢。

詹姆斯

3 个答案:

答案 0 :(得分:1)

尝试使整个方法通用(并使用函数而不是sub):

Public Function GetTable(Of T)() As Table(Of T)

答案 1 :(得分:1)

在回答之前,我有两个评论:

  • 我同意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)。

答案 2 :(得分:0)

请看几个我认为你问的例子: