Сбой Convert.ChangeType () на Nullable Types

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

string modelProperty = "Some Property Name";
string value = "SomeValue";
var property = entity.GetType().GetProperty(modelProperty);
if (property != null) {
    property.SetValue(entity, 
        Convert.ChangeType(value, property.PropertyType), null);
}

Проблема в том, что это приводит к сбою и выбрасывает исключение недопустимого приведения, когда тип свойства имеет тип NULL. Это не тот случай, когда значения невозможно преобразовать - они будут работать, если я сделаю это вручную (например, DateTime? D = Convert.ToDateTime (value); ) Я видел несколько похожих вопросов, но до сих пор не могу заставить его работать.

287
задан dtb 20 August 2010 в 02:39
поделиться

2 ответа

Не проверено, но, возможно, что-то будет работать так:

string modelProperty = "Some Property Name";
string value = "Some Value";

var property = entity.GetType().GetProperty(modelProperty);
if (property != null)
{
    Type t = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;

    object safeValue = (value == null) ? null : Convert.ChangeType(value, t);

    property.SetValue(entity, safeValue, null);
}
389
ответ дан 23 November 2019 в 01:48
поделиться

Для этого нужно получить базовый тип...

Попробуйте это, я успешно использовал это с дженериками:

//Coalesce to get actual property type...
Type t = property.PropertyType();
t = Nullable.GetUnderlyingType(t) ?? t;

//Coalesce to set the safe value using default(t) or the safe type.
safeValue = value == null ? default(t) : Convert.ChangeType(value, t);

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

public static T GetValue<T>(this IDataReader dr, string fieldName)
{
    object value = dr[fieldName];

    Type t = typeof(T);
    t = Nullable.GetUnderlyingType(t) ?? t;

    return (value == null || DBNull.Value.Equals(value)) ? 
        default(T) : (T)Convert.ChangeType(value, t);
}

Вызывается с помощью:

string field1 = dr.GetValue<string>("field1");
int? field2 = dr.GetValue<int?>("field2");
DateTime field3 = dr.GetValue<DateTime>("field3");

Я написал серию постов в блоге, включая это, на http://www. endswithsaurus.com/2010_07_01_archive.html (Прокрутите вниз до Дополнения, @JohnMacintyre действительно заметил ошибку в моем первоначальном коде, которая привела меня по тому же пути, по которому вы идете сейчас). После этого сообщения я сделал пару небольших изменений, которые включают преобразование типов перечислений, так что если ваше свойство является Enum, вы можете использовать тот же вызов метода. Просто добавьте строку для проверки типов перечислений, и вы сможете использовать что-то вроде:

if (t.IsEnum)
    return (T)Enum.Parse(t, value);

Обычно вы проверяете ошибки или используете TryParse вместо Parse, но вы поняли суть.

72
ответ дан 23 November 2019 в 01:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: