views:

2123

answers:

5

I'm attempting to create a dataset based on the properties of an object. For example, I have an instance of a Person class with properties including ID, Forename, Surname, DOB etc. Using reflection, I'm adding columns to a new dataset based on the object properties:

For Each pi As PropertyInfo In person.GetType().GetProperties()
    Dim column As New DataColumn(pi.Name, pi.PropertyType)
    table.Columns.Add(column)
Next

My problem is that some of those properies are nullable types which aren't supported by datasets. Is there any way to extract the underlying system type from a nullable type?

Thanks.

+1  A: 

I'm guessing that the problem is recognizing whether the property is nullable or not. In C# you do this with this code:

if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))

... but I'm not sure what the equivalent of that last clause is in VB.NET.

Matt Hamilton
if (type.IsGenericType AndAlso type.GetGenericTypeDefinition Is GetType(Nullable))
Jonathan Allen
That's actually not a correct translation to VB, bizarrely enough. Check out my answer.
Brian MacKay
Yes, `Nullable` and `Nullable<>` are two different types.
Christian Hayter
A: 

@Mendelt Siebenga: You can only call GetType on the value property if the variable is not set to null; otherwise, you'll get an exception.

What you want to do is use the "GetValueOrDefault" property and call GetType on that, since you are guaranteed it will not be null. Example:

Dim i As Nullable(Of Integer) = Nothing
Dim t As Type = i.GetValueOrDefault().GetType()
Ed Schwehm
A: 

You can also use the GetGenericParameters() method on that type. myNullableObject.GetType().GetGenericParameters()[0] should give you the type of nullable it is (so Guid, Int32, etc.)

Anderson Imes
+8  A: 

Here's your answer, in VB. This may be overkill for your purposes, but it also might be useful to some other folks.

First off, here's the code to find out if you're dealing with a Nullable type:

Private Function IsNullableType(ByVal myType As Type) As Boolean
    Return (myType.IsGenericType) AndAlso (myType.GetGenericTypeDefinition() Is GetType(Nullable(Of )))
End Function

Note the unusual syntax in the GetType. It's necessary. Just doing GetType(Nullable) as one of the commentors suggested did not work for me.

So, armed with that, you can do something like this... Here, in an ORM tool, I am trying to get values into a generic type that may or not be Nullable:

If (Not value Is Nothing) AndAlso IsNullableType(GetType(T)) Then
    Dim UnderlyingType As Type = Nullable.GetUnderlyingType(GetType(T))
    Me.InnerValue = Convert.ChangeType(value, UnderlyingType)
Else
    Me.InnerValue = value
End If

Note that I check for Nothing in the first line because Convert.ChangeType will choke on it... You may not have that problem, but my situation is extremely open-ended.

Hopefully if I didn't answer your question directly, you can cannibalize this and get you where you need to go - but I just implemented this moments ago, and my tests are all passing.

Brian MacKay
All he asked for was the underlying type so all you need is Nullable.GetUnderlyingType.
Bryan Anderson
I suspect he will end up needing most of it. :)
Brian MacKay
Excellent post, saved my ass!
tbone
Really glad to hear it tbone.
Brian MacKay
good stuff, exactly what I needed
andy
Awesome, glad to help. :)
Brian MacKay
A: 
Nullable.GetUnderylingType(myType)

will return the underlying type or null if it's not a nullable type.

herzmeister der welten