通过使用string值进行reflection来设置属性
我想通过Reflection来设置一个对象的属性,其值为string
types。 所以,举个例子,假设我有一个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”types的对象不能转换为“System.Double”types。
如何根据propertyInfo
将值转换为正确的types?
您可以使用Convert.ChangeType()
– 它允许您使用任何IConvertible
types的运行时信息来更改表示forms。 但是,并非所有的转换都是可能的,如果您要支持非IConvertible
types的转换,则可能需要编写特殊情况逻辑。
相应的代码(没有exception处理或特殊情况逻辑)将是:
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);
事实上,我build议你看看整个Convert
类 。
这个类和许多其他有用的类是System
Namespace的一部分。 我觉得每年都要扫描一下这个命名空间是很有用的,看看我错过了什么function。 试一试!
我注意到很多人推荐Convert.ChangeType
– 这对一些情况有效,但是一旦你开始涉及nullable
types,你将开始接收InvalidCastExceptions
:
几年前写了一个包装器来处理这个问题,但这并不完美。
你可以使用一个types转换器(无错误检查):
Ship ship = new Ship(); string value = "5.5"; var property = ship.GetType().GetProperty("Latitude"); var convertedValue = property.Converter.ConvertFrom(value); property.SetValue(self, convertedValue);
就组织代码而言,你可以创build一种类似的混合 ,这将导致代码如下所示:
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
可以重用于许多不同的类。
您也可以创build自己的自定义types转换器来附加到您的属性或类:
public class Ship : MPropertyAsStringSettable { public Latitude Latitude { get; set; } // ... } [TypeConverter(typeof(LatitudeConverter))] public class Latitude { ... }
您可能正在寻找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
转换的types。
propertyInfo.SetValue( ship, Convert.ChangeType( value, propertyInfo.PropertyType ), null );
或者你可以尝试:
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");
我试着从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); }
你是否在寻找反思,或者你正在寻找一个生产软件? 我会质疑你为什么使用reflection设置属性。
Double new_latitude; Double.TryParse (value, out new_latitude); ship.Latitude = new_latitude;