Establecer una propiedad por reflexión con un valor de cadena
Me gustaría establecer una propiedad de un objeto a través de 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);
Tal como está, esto arroja un ArgumentException
:
Objeto de tipo 'System.Cadena 'no se puede convertir a tipo' Sistema.Doble.
¿Cómo puedo convertir el valor al tipo adecuado, basado en propertyInfo
?
11 answers
Puede utilizar Convert.ChangeType()
- Le permite usar información de tiempo de ejecución en cualquier tipo IConvertible
para cambiar los formatos de representación. Sin embargo, no todas las conversiones son posibles, y es posible que deba escribir una lógica de mayúsculas y minúsculas especial si desea admitir conversiones de tipos que no son IConvertible
.
El código correspondiente (sin manejo de excepciones o lógica de casos especiales) 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);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-06 08:31:45
Como muchos otros han dicho, quieres usar Convert.ChangeType
:
propertyInfo.SetValue(ship,
Convert.ChangeType(value, propertyInfo.PropertyType),
null);
De hecho, le recomiendo que mire todo el Convert
Clase .
Esta clase, y muchas otras clases útiles son parte de la System
espacio de Nombres. Me resulta útil escanear ese espacio de nombres cada año más o menos para ver qué características me he perdido. ¡Inténtalo!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-06 08:57:13
Noto que mucha gente está recomendando Convert.ChangeType
- Esto funciona para algunos casos, sin embargo, tan pronto como comience a involucrar nullable
tipos comenzará a recibir InvalidCastExceptions
:
Hace unos años se escribió un wrapper para manejar esto, pero eso tampoco es perfecto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-06 09:09:27
Puede usar 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 términos de organizar el código, podría 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
puede ser reutilizado para muchas clases diferentes.
También puede crear sus propios convertidores de tipo personalizados para adjuntarlos a sus propiedades o clases:
public class Ship : MPropertyAsStringSettable {
public Latitude Latitude { get; set; }
// ...
}
[TypeConverter(typeof(LatitudeConverter))]
public class Latitude { ... }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-15 10:48:55
Probablemente estés buscando el Convert.ChangeType
método. Por ejemplo:
Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-06 20:48:30
Usando Convert.ChangeType
y obteniendo el tipo a convertir de PropertyInfo.PropertyType
.
propertyInfo.SetValue( ship,
Convert.ChangeType( value, propertyInfo.PropertyType ),
null );
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-06 08:47:06
Probé la respuesta de LBushkin y funcionó muy bien, pero no funcionará para valores null y campos nullables. Así que lo 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);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-04 14:51:33
O puedes intentar:
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);
//But this will cause problems if your string value IsNullOrEmplty...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-06 20:47:37
Si está escribiendo la aplicación Metro, debe usar otro 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");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-10 08:22:55
Responderé esto con una respuesta general. Por lo general, estas respuestas no funcionan con guid. Aquí hay 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);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-30 08:35:04
¿Está buscando jugar con la reflexión o está buscando construir una pieza de producción de software? Me preguntaría por qué estás usando reflexión para establecer una propiedad.
Double new_latitude;
Double.TryParse (value, out new_latitude);
ship.Latitude = new_latitude;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-06 20:57:55