Setting a property by reflection with a string val

2019-01-01 03:07发布

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.

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:

Object of type 'System.String' cannot be converted to type 'System.Double'.

How can I convert value to the proper type, based on propertyInfo?

11条回答
余生无你
2楼-- · 2019-01-01 03:36

I will answer this with a general answer. Usually these answers not working with guids. Here is a working version with guids too.

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); 
查看更多
公子世无双
3楼-- · 2019-01-01 03:37

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.

Double new_latitude;

Double.TryParse (value, out new_latitude);
ship.Latitude = new_latitude;
查看更多
路过你的时光
4楼-- · 2019-01-01 03:40

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:

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

A wrapper was written a few years ago to handle this but that isn't perfect either.

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

查看更多
荒废的爱情
5楼-- · 2019-01-01 03:44

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 mixin that would result in code like this:

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.

You can also create your own custom type converters to attach to your properties or classes:

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

[TypeConverter(typeof(LatitudeConverter))]
public class Latitude { ... }
查看更多
零度萤火
6楼-- · 2019-01-01 03:44

I tried the answer from LBushkin and it worked great, but it won't work for null values and nullable fields. So I've changed it to this:

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);
}
查看更多
登录 后发表回答