views:

2110

answers:

10

Hi, 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 Argument exception (Object of type 'System.String' cannot be converted to type 'System.Double').

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

+5  A: 

As several others have said, you want to use Convert.ChangeType:

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

In fact, I recommend you look at the entire 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!

John Saunders
The OP probably wants the general answer, for setting a property of any type that has an obvious conversion from a string.
Daniel Earwicker
Good point. I'll edit and point to the real answerers, or will delete mine if someone will add what I said about the rest of the namespace.
John Saunders
+18  A: 

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.

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);
LBushkin
A: 

Or you could try:

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

//But this will cause problems if your string value IsNullOrEmplty...
J.13.L
+1  A: 

You're probably looking for the Convert.ChangeType method. For example:

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

Using Convert.ChangeType and getting the type to convert to from the PropertyInfo.PropertyType.

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

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;
A: 

You guy are doing a great job. Keep it up.

A: 

Hi, 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

Shahin
A: 

Nice guys, thank you sooo much.

Kosti
A: 

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 (using a type converter, no error checking):

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 { ... }
Jordão