Я хочу преобразовать строку в значение свойства объекта, имя которого у меня есть в виде строки. Я пытаюсь сделать это следующим образом:
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);
) Я видел несколько похожих вопросов, но до сих пор не могу заставить его работать.
Не проверено, но, возможно, что-то будет работать так:
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);
}
Для этого нужно получить базовый тип...
Попробуйте это, я успешно использовал это с дженериками:
//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, но вы поняли суть.