通过反射使用字符串值设置属性

时间:2009-07-06 20:43:19

标签: c# reflection type-conversion propertyinfo setvalue

我想通过Reflection设置对象的属性,其值为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.String'类型的对象无法转换为'System.Double'类型。

如何根据propertyInfo

将值转换为正确的类型

12 个答案:

答案 0 :(得分:477)

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

答案 1 :(得分:32)

正如其他几位人士所说,你想使用Convert.ChangeType

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

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

这个类以及许多其他有用的类都是System Namespace的一部分。我发现每年扫描一个命名空间很有用,看看我错过了哪些功能。试一试!

答案 2 :(得分:19)

我注意到很多人都在推荐Convert.ChangeType - 这确实适用于某些情况但是一旦您开始涉及nullable类型,您就会开始接收InvalidCastExceptions

  

http://weblogs.asp.net/pjohnson/archive/2006/02/07/Convert.ChangeType-doesn_2700_t-handle-nullables.aspx

几年前写了一个封装器来处理这个问题,但这也不完美。

  

http://weblogs.asp.net/pjohnson/archive/2006/02/07/Convert.ChangeType-doesn_2700_t-handle-nullables.aspx

答案 3 :(得分:11)

您可以使用类型转换器(无错误检查):

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

在组织代码方面,你可以创建一个kind-of 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可以在许多不同的类中重复使用。

您还可以创建自己的自定义type converters以附加到您的媒体资源或类别:

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

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

答案 4 :(得分:9)

我尝试了 LBushkin 的答案,但效果很好,但它不适用于空值和可空字段。所以我把它改成了这个:

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);
}

答案 5 :(得分:6)

您可能正在寻找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);

答案 6 :(得分:5)

使用Convert.ChangeType并获取要从PropertyInfo.PropertyType转换的类型。

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

答案 7 :(得分:4)

我将以一般性答案回答这个问题。通常这些答案不适用于guids。这是一个带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); 

答案 8 :(得分:3)

或者你可以试试:

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

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

答案 9 :(得分:2)

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

答案 10 :(得分:0)

使用以下代码应该可以解决您的问题:

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

答案 11 :(得分:-7)

您是否希望使用Reflection进行游戏,还是希望构建一个生产软件?我会问你为什么要使用反射来设置属性。

Double new_latitude;

Double.TryParse (value, out new_latitude);
ship.Latitude = new_latitude;