Установка свойства путем отражения со строковым значением

StackOverflow https://stackoverflow.com/questions/1089123

Вопрос

Я бы хотел установить свойство объекта посредством отражения со значением типа string.Итак, например, предположим, что у меня есть Ship класс, обладающий свойством Latitude, который является double.

Вот что я хотел бы сделать:

Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, value, null);

Как есть, это бросает ArgumentException:

Объект типа 'System.Строка' не может быть преобразована в тип 'System.Double'.

Как я могу преобразовать значение в правильный тип, основываясь на propertyInfo?

Это было полезно?

Решение

Вы можете использовать Convert.ChangeType() - Это позволяет вам использовать информацию о времени выполнения на любом IConvertible введите, чтобы изменить форматы представления.Однако возможны не все преобразования, и вам может потребоваться написать специальную логику обращения, если вы хотите поддерживать преобразования из типов, которые не IConvertible.

Соответствующий код (без обработки исключений или логики особого случая) был бы:

Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);

Другие советы

Как уже говорили несколько других, вы хотите использовать Convert.ChangeType:

propertyInfo.SetValue(ship,
    Convert.ChangeType(value, propertyInfo.PropertyType),
    null);

На самом деле, я рекомендую вам взглянуть на весь Convert Класс.

Этот класс и многие другие полезные классы являются частью System Пространство имен.Я считаю полезным сканировать это пространство имен каждый год или около того, чтобы увидеть, какие функции я пропустил.Дайте ему попробовать!

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

http://weblogs.asp.net/pjohnson/archive/2006/02/07/Convert .Тип изменения-doesn_2700_t-обрабатывает-nullables.aspx

Несколько лет назад была написана оболочка для решения этой проблемы, но она тоже не идеальна.

http://weblogs.asp.net/pjohnson/archive/2006/02/07/Convert .Тип изменения-doesn_2700_t-обрабатывает-nullables.aspx

Вы можете использовать преобразователь типов (без проверки ошибок):

Ship ship = new Ship();
string value = "5.5";
var property = ship.GetType().GetProperty("Latitude");
var convertedValue = property.Converter.ConvertFrom(value);
property.SetValue(self, convertedValue);

С точки зрения организации кода, вы могли бы создать своеобразная смесь это привело бы к такому коду, как этот:

Ship ship = new Ship();
ship.SetPropertyAsString("Latitude", "5.5");

Это было бы достигнуто с помощью этого кода:

public interface MPropertyAsStringSettable { }
public static class PropertyAsStringSettable {
  public static void SetPropertyAsString(
    this MPropertyAsStringSettable self, string propertyName, string value) {
    var property = TypeDescriptor.GetProperties(self)[propertyName];
    var convertedValue = property.Converter.ConvertFrom(value);
    property.SetValue(self, convertedValue);
  }
}

public class Ship : MPropertyAsStringSettable {
  public double Latitude { get; set; }
  // ...
}

MPropertyAsStringSettable может быть повторно использован для многих различных классов.

Вы также можете создать свой собственный пользовательский преобразователи типов для прикрепления к вашим свойствам или классам:

public class Ship : MPropertyAsStringSettable {
  public Latitude Latitude { get; set; }
  // ...
}

[TypeConverter(typeof(LatitudeConverter))]
public class Latitude { ... }

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

propertyName= "Latitude";
PropertyInfo propertyInfo = ship.GetType().GetProperty(propertyName);
if (propertyInfo != null)
{
     Type t = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;
     object safeValue = (value == null) ? null : Convert.ChangeType(value, t);
     propertyInfo.SetValue(ship, safeValue, null);
}

Вы, вероятно, ищете Convert.ChangeType способ.Например:

Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);

Используя Convert.ChangeType и получение типа для преобразования из PropertyInfo.PropertyType.

propertyInfo.SetValue( ship,
                       Convert.ChangeType( value, propertyInfo.PropertyType ),
                       null );

Я отвечу на это общим ответом.Обычно эти ответы не работают с идентификаторами guid.Вот рабочая версия с идентификаторами guid тоже.

var stringVal="6e3ba183-89d9-e611-80c2-00155dcfb231"; // guid value as string to set
var prop = obj.GetType().GetProperty("FooGuidProperty"); // property to be setted
var propType = prop.PropertyType;

// var will be type of guid here
var valWithRealType = TypeDescriptor.GetConverter(propType).ConvertFrom(stringVal); 

Или вы могли бы попробовать:

propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);

//But this will cause problems if your string value IsNullOrEmplty...

Если вы пишете приложение Metro, вам следует использовать другой код:

Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetTypeInfo().GetDeclaredProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType));

Примечание:

ship.GetType().GetTypeInfo().GetDeclaredProperty("Latitude");

вместо того , чтобы

ship.GetType().GetProperty("Latitude");

Использование следующего кода должно решить вашу проблему:

item.SetProperty(prop.Name, Convert.ChangeType(item.GetProperty(prop.Name).ToString().Trim(), prop.PropertyType));

Вы хотите поиграть с Reflection или хотите создать производственную часть программного обеспечения?Я бы задался вопросом, почему вы используете отражение для установки свойства.

Double new_latitude;

Double.TryParse (value, out new_latitude);
ship.Latitude = new_latitude;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top