在运行时转换为泛型类型

时间:2010-09-09 20:50:37

标签: vb.net generics reflection

好的,我不认为这是可能的,所以我想我会要求确定。我正在创建一个函数,它反映了类中的属性,并将它们添加到我拥有的数据结构中。一些属性是泛型类型。

所以说我们DataType(Of T)的{​​{1}}属性类型为.Value

T

在原始类型的Dim properties = GetType(MyType).GetFields(Reflection.BindingFlags.Public Or _ Reflection.BindingFlags.Instance) For Each prop As fieldinfo In properties Collection.Add(prop.Name,prop.GetValue(poco)) Next collection.AddInteger等......)我只想添加类型...但在泛型的情况下我想添加String。我希望有一些解决办法,但我认为没有办法,因为DataType(Of T).Value的类型无法在编译时确定吗?理想情况下T是可能的。这是你希望在.NET 4.0中出现更多动态的时候。

2 个答案:

答案 0 :(得分:1)

我刚想到我可能误读了你的问题。因此,我的另一个答案。

通过引入允许访问某些Value属性的新接口,您可以避免在运行时强制转换为泛型类型(您不知道类型参数):

Public Interface IHasValue
    Public ReadOnly Property Value As Object
End Interface

接下来,确保您的DataType(Of T)类实现此接口。这意味着每个DataType(Of T)对象(无论具体类型为T)也是IHasValue,您可以使用TypeOf(…) Is IHasValue进行检查:

Public Class DataType(Of T) : Implements IHasValue

    Public Value As T

    Public ReadOnly Property UntypedValue As Object Implements IHasValue.Value
        Get
            Return Me.Value
        End Get
    End Property

End Class

Value的重复是必要的,原因有二:首先,DataType(Of T).Value是字段而不是属性,第二是因为它们没有相同的类型。)

然后,在您使用字段填充集合的位置,您可以通过执行以下操作来检查特定字段是否为DataType(Of T)(如果是,则从中解包Value):

Dim value As Object = prop.GetValue(poco)

If TypeOf(value) Is IHasValue Then         ' <- is value a DataType(Of T) ?    '
    value = CType(value, IHasValue).Value  ' <- if so, unwrap the value        '
End If

Collection.Add(prop.Name, value)

这可能比我的其他答案更多,但我要强调一下:

  

If TypeOf(…) Is … Then …是代码气味。也许你应该重新思考你的代码并研究涉及多态的解决方案。

答案 1 :(得分:0)

首先,我对您尝试做的事情的假设:

  1. 您有一个名为poco的对象,其类型为MyType

  2. MyType包含不同类型的字段,因此您认为需要泛型。

  3. 您有一个名为Collection的键值对集合,可能有Dictionary(Of String, Object)类型?

  4. 您希望将poco的所有字段(即其名称和值)转移到Collection


  5.   

    边节点:您正在使用属性混合字段:您的代码在字段上运行(通过调用GetFields),而您的问题文本则说明属性。它们不是一回事!


    其次,关于集合和静态类型系统的一些基本事实:

    • 无类型集合(其中项目类型为Object)可以在其中存储各种值。

    • 类型集合(其中项目属于更具体的类型,例如T)只能存储类型为T的值或从T派生的类型。


    第三,从上面得出的结论:

    • 在您的情况下,Collection必须是无类型的集合,如果确实poco(类型MyType)具有不同类型的字段。

    • 在这种情况下,泛型实际上根本不会帮助你,因为这不是泛型的用途。当您想要定义操作(即方法,行为)时,泛型非常有用,无论它们处理何种类型的对象,它们都以相同的方式工作。

      例如,List(Of T)定义了一种集合类型,无论T是什么类型,它都可以正常工作。但这并不意味着您可以在List(Of T)中放置任何内容,因为只要您实例化此类型 - 例如使用Dim xs As New List(Of String) - ,T将固定为特定类型 - String - ,最终会得到一个仅接受此类值的类型集合。

      所以,再次:如果您需要一个存储不同类型对象的集合,请选择Object作为值类型,而不是尝试查找涉及泛型的解决方案。


    话虽如此,还有另一种解决方案:多态

    如果您希望代码以不同的方式处理值,则根据其类型,可以采用多态性:

    • 首先,您定义了一个接口或一个抽象基类(例如DataType,尽管我强烈建议您选择一个更加不言自明的名称!),它指定了您的值可以做什么

    • 其次,将Collection键入Dictionary(Of String, DataType)。这意味着只有DataType类型的对象或从中派生的任何对象才能进入集合。

    • 第三,派生自/实施DataType以指定特定类型的行为。

    这里有一个很好的slide show called Conditionals and Polymorphism


      

    旁注:最后但并非最不重要的是,您可以找出泛型类型参数的类型:TypeOf(T)