VB.NET Получить базовый тип system.type от типа NULL

Я пытаюсь создать набор данных, основанный на свойствах объекта. Например, у меня есть экземпляр класса Person со свойствами, включая ID, Forename, Surname, DOB и т.д. Используя отражение, я добавляю столбцы в новый набор данных на основе свойств объекта:

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

Моя проблема заключается в том, что некоторые из этих свойств являются типами NULL, которые не поддерживаются наборами данных. Есть ли способ извлечь базовый тип системы из типа NULL?

Спасибо.

Ответ 1

Вот ваш ответ, в VB. Это может быть излишним для ваших целей, но это также может быть полезно для некоторых других людей.

Прежде всего, вот код, чтобы узнать, имеете ли вы дело с типом Nullable:

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

Обратите внимание на необычный синтаксис в GetType. Это необходимо. Просто делать GetType (Nullable), поскольку один из предложенных комментариев не работал у меня.

Итак, вооружившись этим, вы можете сделать что-то вроде этого... Здесь, в инструменте ORM, я пытаюсь получить значения в общий тип, который может быть или не быть 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

Обратите внимание, что я проверяю Nothing в первой строке, потому что Convert.ChangeType задушит его... У вас может не быть этой проблемы, но моя ситуация чрезвычайно открыта.

Надеюсь, если бы я не ответил на ваш вопрос напрямую, вы можете cannibalize это и получить вас, куда вам нужно идти - но я только что реализовал это несколько минут назад, и мои тесты проходят.

Ответ 2

Nullable.GetUnderylingType(myType)

возвращает базовый тип или null, если он не является типом с нулевым значением.

Ответ 3

Вы также можете использовать метод GetGenericParameters() для этого типа. myNullableObject.GetType().GetGenericParameters()[0] должен указывать тип нулеустойчивости (так Guid, Int32 и т.д.)

Ответ 4

Я предполагаю, что проблема заключается в признании того, является ли свойство нулевым или нет. В С# вы делаете это с помощью этого кода:

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

... но я не уверен, что эквивалент последнего предложения в VB.NET.

Ответ 5

@Mendelt Siebenga: Вы можете вызвать GetType только для свойства value, если переменная не установлена ​​в null; в противном случае вы получите исключение.

Что вы хотите сделать, это использовать свойство GetValueOrDefault и вызывать GetType, поскольку вам гарантировано, что он не будет равен нулю. Пример:

Dim i As Nullable(Of Integer) = Nothing
Dim t As Type = i.GetValueOrDefault().GetType()