我想通过反射设置一个对象的属性,值类型为字符串。 例如,假设我有一个Ship类,它的纬度属性是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?


当前回答

你可以使用类型转换器(没有错误检查):

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

在组织代码方面,你可以创建一种mixin,结果是这样的代码:

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 { ... }

其他回答

如果你正在编写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");

你可能在找皈依者。ChangeType功能。例如:

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

使用下面的代码可以解决你的问题:

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

正如其他几个人所说,您希望使用Convert。ChangeType:

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

事实上,我建议您查看整个Convert Class。

这个类和许多其他有用的类都是系统名称空间的一部分。我发现,大约每隔一年扫描一下这个名称空间,看看我遗漏了哪些特性,这很有用。试试吧!

你可以使用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);