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

问题描述:

我想创建一个特定类型的对象。我有下面的代码,但是它失败了,因为它不能将新的表格对象转换为已经定义的表格对象。我需要表来启动一个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 

所以简言之 - 有没有办法在运行时更改变量类型? (或做我在做什么更好的办法)提前

感谢。

詹姆斯

看看这些一对夫妇的什么,我认为你的例子都在问:

尝试使整个方法的通用(和使用功能而不是子功能):

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

回答之前,我的确是有两个的话:

  • 我与乔尔同意,一个通用的解决方案就会简单得多,但没有更多的情况下,我会假设你真的需要反思
  • 为什么你使用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的(以产品)转换为IEnumerable(Of Object)类型的变量。

Here's an explanation of co- and contravariance in VB.Net

所以,你可以做的是定义为通用表的接口:

Interface ITable(Of Out T) 
End Interface 

然后你可以在通用表类实现这个接口:

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)。