Coder Perfect

Reflection is used to set a property with a string value.

Problem

I’d want to use Reflection to set a property of an object with a string value. So, let’s say I have a Ship class with a double-valued attribute called Latitude.

What I’d like to do is:

Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, value, null);

As is, an ArgumentException is thrown:

How can I use propertyInfo to transform a value to the correct type?

Asked by David Hodgson

Solution #1

Convert is an option. ChangeType() allows you to alter representation formats using runtime information on any IConvertible type. Not all conversions are possible, and if you wish to support conversions from types that aren’t IConvertible, you may need to implement special case logic.

Without exception handling or special case logic, the corresponding code 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);

Answered by LBushkin

Solution #2

You should use Convert, as several people have suggested. ChangeType:

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

In fact, I strongly advise you to take a look at the complete Convert Class.

The System Namespace contains this and many other essential classes. Every year or so, I scan that namespace to see what features I’ve overlooked. Give it a shot.

Answered by John Saunders

Solution #3

I’ve seen that a lot of folks endorse Convert. ChangeType – This works in some circumstances, but once you start working with nullable types, you’ll start getting InvalidCastExceptions:

A wrapper was created to handle this a few years ago, although it isn’t ideal.

Answered by Tablet

Solution #4

I tried LBushkin’s solution, and it worked perfectly, but it won’t work with null values or nullable fields. As a result, I’ve altered it to:

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

Answered by Ashkan Sirous

Solution #5

You can use the following type converter (which does not check for errors):

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 code organization, you could design a mixin that outputs something like this:

Ship ship = new Ship();
ship.SetPropertyAsString("Latitude", "5.5");

This could be accomplished with the following 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; }
  // ...
}

Many distinct classes can utilize MPropertyAsStringSettable.

You can also make your own type converters to use with your properties or classes:

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

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

Answered by Jordão

Post is based on https://stackoverflow.com/questions/1089123/setting-a-property-by-reflection-with-a-string-value