C# 使用字符串值通过反射设置属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1089123/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Setting a property by reflection with a string value
提问by David Hodgson
I'd like to set a property of an object through Reflection, with a value of type string
.
So, for instance, suppose I have a Ship
class, with a property of Latitude
, which is a double
.
我想通过反射设置对象的属性,其值为 type string
。所以,举例来说,假设我有一Ship
类,具有的属性Latitude
,这是一个double
。
Here's what I'd like to do:
这是我想要做的:
Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, value, null);
As is, this throws an ArgumentException
:
照原样,这会抛出一个ArgumentException
:
Object of type 'System.String' cannot be converted to type 'System.Double'.
“System.String”类型的对象无法转换为“System.Double”类型。
How can I convert value to the proper type, based on propertyInfo
?
如何将值转换为正确的类型,基于propertyInfo
?
采纳答案by LBushkin
You can use Convert.ChangeType()
- It allows you to use runtime information on any IConvertible
type to change representation formats. Not all conversions are possible, though, and you may need to write special case logic if you want to support conversions from types that are not IConvertible
.
您可以使用Convert.ChangeType()
- 它允许您使用任何IConvertible
类型的运行时信息来更改表示格式。但是,并非所有转换都是可能的,如果您想支持来自非IConvertible
.
The corresponding code (without exception handling or special case logic) would be:
相应的代码(没有异常处理或特殊情况逻辑)将是:
Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);
回答by John Saunders
As several others have said, you want to use Convert.ChangeType
:
正如其他几个人所说,您想使用Convert.ChangeType
:
propertyInfo.SetValue(ship,
Convert.ChangeType(value, propertyInfo.PropertyType),
null);
In fact, I recommend you look at the entire Convert
Class.
实际上,我建议您查看整个Convert
Class。
This class, and many other useful classes are part of the System
Namespace. I find it useful to scan that namespace every year or so to see what features I've missed. Give it a try!
这个类和许多其他有用的类是System
Namespace 的一部分。我发现每年左右扫描该命名空间以查看我错过了哪些功能很有用。试一试!
回答by bytebender
Or you could try:
或者你可以试试:
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);
//But this will cause problems if your string value IsNullOrEmplty...
回答by John Calsbeek
You're probably looking for the Convert.ChangeType
method. For example:
您可能正在寻找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);
回答by tvanfosson
Using Convert.ChangeType
and getting the type to convert from the PropertyInfo.PropertyType
.
使用Convert.ChangeType
和获取要从PropertyInfo.PropertyType
.
propertyInfo.SetValue( ship,
Convert.ChangeType( value, propertyInfo.PropertyType ),
null );
回答by clemahieu
Are you looking to play around with Reflection or are you looking to build a production piece of software? I would question why you're using reflection to set a property.
您是想使用 Reflection 还是想构建一个生产软件?我会质疑您为什么使用反射来设置属性。
Double new_latitude;
Double.TryParse (value, out new_latitude);
ship.Latitude = new_latitude;
回答by Tablet
I notice a lot of people are recommending Convert.ChangeType
- This does work for some cases however as soon as you start involving nullable
types you will start receiving InvalidCastExceptions
:
我注意到很多人都在推荐Convert.ChangeType
- 这在某些情况下确实有效,但是一旦您开始涉及nullable
类型,您就会开始收到InvalidCastExceptions
:
A wrapper was written a few years ago to handle this but that isn't perfect either.
几年前编写了一个包装器来处理这个问题,但这也不完美。
回答by Jord?o
You can use a type converter (no error checking):
您可以使用类型转换器(无错误检查):
Ship ship = new Ship();
string value = "5.5";
var property = ship.GetType().GetProperty("Latitude");
var convertedValue = property.Converter.ConvertFrom(value);
property.SetValue(self, convertedValue);
In terms of organizing the code, you could create a kind-of mixinthat would result in code like this:
在组织代码方面,您可以创建一种类似这样的 mixin代码:
Ship ship = new Ship();
ship.SetPropertyAsString("Latitude", "5.5");
This would be achieved with this code:
这将通过以下代码实现:
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
can be reused for many different classes.
MPropertyAsStringSettable
可以重用于许多不同的类。
You can also create your own custom type convertersto attach to your properties or classes:
您还可以创建自己的自定义类型转换器以附加到您的属性或类:
public class Ship : MPropertyAsStringSettable {
public Latitude Latitude { get; set; }
// ...
}
[TypeConverter(typeof(LatitudeConverter))]
public class Latitude { ... }
回答by Serhiy
If you are writing Metro app, you should use other code:
如果您正在编写 Metro 应用程序,您应该使用其他代码:
Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetTypeInfo().GetDeclaredProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType));
Note:
笔记:
ship.GetType().GetTypeInfo().GetDeclaredProperty("Latitude");
instead of
代替
ship.GetType().GetProperty("Latitude");
回答by Ashkan Sirous
I tried the answer from LBushkinand it worked great, but it won't work for null values and nullable fields. So I've changed it to this:
我尝试了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);
}