反射并在运行时更改变量类型?
问题描述:
我想创建一个特定类型的对象。我有下面的代码,但是它失败了,因为它不能将新的表格对象转换为已经定义的表格对象。我需要表来启动一个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)。