Pregunta

Me gustaría establecer una propiedad de un objeto a través de la reflexión, con un valor de tipo string. Así, por ejemplo, supongamos que tengo una clase Ship, con una propiedad de Latitude, que es un double.

Esto es lo que me gustaría hacer:

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

Como es, esto arroja una ArgumentException:

  

objeto de tipo 'System.String' no se puede convertir al tipo 'System.Double'.

¿Cómo puedo convertir el valor al tipo adecuado, basado en propertyInfo?

¿Fue útil?

Solución

Puede utilizar Convert.ChangeType() - Se permite el uso de información de tiempo de ejecución en cualquier tipo IConvertible para cambiar formatos de representación. No todas las conversiones son posibles, sin embargo, y puede que tenga que escribir la lógica de casos especiales, si quieres apoyar las conversiones de tipos que no están IConvertible.

El código correspondiente (sin tratamiento de excepciones o lógica especial caso) sería:

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

Otros consejos

Como muchos otros han dicho, que desea utilizar Convert.ChangeType:

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

De hecho, le recomiendo que busque en toda la Convert Clase .

Esta clase, y muchas otras clases útiles son parte de la System Espacio de nombres . Me resulta útil para explorar ese espacio de nombres o menos cada año para ver qué características que he perdido. Darle una oportunidad!

Me he dado cuenta de una gran cantidad de personas están recomendando Convert.ChangeType - Esto funciona para algunos casos, sin embargo, tan pronto como se inicia la participación de tipos nullable usted comenzará a recibir InvalidCastExceptions:

  

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

Una envoltura fue escrito hace unos años para manejar esto, pero que tampoco es perfecta.

  

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

Puede utilizar un convertidor de tipos (sin comprobación de errores):

Ship ship = new Ship();
string value = "5.5";
var property = ship.GetType().GetProperty("Latitude");
var convertedValue = property.Converter.ConvertFrom(value);
property.SetValue(self, convertedValue);

En cuanto a la organización del código, se puede crear un tipo de mixin que resultaría en código como este:

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

Esto se lograría con este código:

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 se puede reutilizar para muchas clases diferentes.

También puede crear su propia tipo convertidores adjuntar a sus propiedades o clases:

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

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

Probé la respuesta de LBushkin y funcionó muy bien, pero no va a funcionar para valores nulos y anulables campos. Así que he cambiado a esto:

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

El uso de Convert.ChangeType y obtener el tipo de convertir de la PropertyInfo.PropertyType.

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

Voy a responder a esto con una respuesta general. Por lo general, estas respuestas no se trabaja con guids. Aquí está una versión de trabajo con guids también.

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

O usted podría intentar:

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

//But this will cause problems if your string value IsNullOrEmplty...

Si está escribiendo metro aplicación, se debe utilizar otro tipo de código:

Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetTypeInfo().GetDeclaredProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType));

Nota:

ship.GetType().GetTypeInfo().GetDeclaredProperty("Latitude");

en lugar de

ship.GetType().GetProperty("Latitude");

Usando el siguiente código debería resolver el problema:

item.SetProperty(prop.Name, Convert.ChangeType(item.GetProperty(prop.Name).ToString().Trim(), prop.PropertyType));

¿Está buscando para jugar un poco con la reflexión o está buscando para construir una pieza de producción de software? Me pregunta por qué estás usando la reflexión para establecer una propiedad.

Double new_latitude;

Double.TryParse (value, out new_latitude);
ship.Latitude = new_latitude;
scroll top