coding4fun
coding4fun

Reputation: 8189

cast to generic type at runtime

Ok, i don't think this is possible so I thought I would ask to make sure. I'm in the process of creating a function which reflects over the properties in a class and adds them to this data structure I have. Some of the properties are generic types.

So say we have DataType(Of T) that has a .Value property of type 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

In the collection.Add for primitive types (Integer, String, etc.…) I just want to add the type... but in the case of generic I want to add the DataType(Of T).Value. I hope there is some work-around but I don't think there is a way because the type of T can not be determined at compile time right? Ideally DirectCast(prop.getvalue(poco), DataType(Of T)).Value would be possible. This is when you hoped even more dynamics appear than whats in .NET 4.0.

Upvotes: 1

Views: 3731

Answers (1)

It just occurred to me that I may have mis-read your question. Therefore another answer from me.

You can avoid the need to cast to a generic type (where you don't know the type parameter) at runtime by introducing a new interface that allows access to some Value property:

Public Interface IHasValue
    Public ReadOnly Property Value As Object
End Interface

Next, make sure your DataType(Of T) class implements this interface. This means that each DataType(Of T) object (no matter what concrete type T is) is also an IHasValue, and you will be able to check this with 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

(This duplication of Value is necessary for two reasons: First it is necessary when DataType(Of T).Value is a field instead of a property, and second because they do not have the same type.)

Then, where you fill your collection with fields, you can check whether a particular field is an DataType(Of T) (and if so, unwrap the Value from it) by doing the following:

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)

This is probably more what you're after than my other answer, but let me emphasise this:

If TypeOf(…) Is … Then … is a code smell. Perhaps you should re-think your code and investigate solutions involving polymorphism.

Upvotes: 1

Related Questions