J'aimerais définir une propriété d'un objet via Reflection, avec une valeur de type string
. Donc, par exemple, supposons que j'ai une classe Ship
, avec une propriété de Latitude
, qui est un double
.
Voici ce que j'aimerais faire:
Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, value, null);
Tel quel, cela jette un ArgumentException
:
Les objets de type 'System.String' ne peuvent pas être convertis en type 'System.Double'.
Comment puis-je convertir la valeur en un type approprié, basé sur propertyInfo
?
Vous pouvez utiliser Convert.ChangeType()
- Il vous permet d'utiliser les informations d'exécution sur tout type IConvertible
pour modifier les formats de représentation. Cependant, toutes les conversions ne sont pas possibles et vous devrez peut-être écrire une logique de casse particulière si vous souhaitez prendre en charge les conversions provenant de types non IConvertible
.
Le code correspondant (sans traitement des exceptions ni logique de cas particulier) serait:
Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);
Comme plusieurs autres l'ont dit, vous voulez utiliser Convert.ChangeType
:
propertyInfo.SetValue(ship,
Convert.ChangeType(value, propertyInfo.PropertyType),
null);
En fait, je vous recommande d’examiner l’ensemble Convert
Class .
Cette classe et de nombreuses autres classes utiles font partie de System
Namespace . Je trouve utile d'analyser cet espace de noms tous les ans environ pour voir les fonctionnalités que j'ai manquées. Essaie!
Je remarque que beaucoup de gens recommandent Convert.ChangeType
- Cela fonctionne dans certains cas, mais dès que vous commencez à utiliser les types nullable
, vous commencerez à recevoir InvalidCastExceptions
:
Un wrapper a été écrit il y a quelques années pour gérer cela, mais ce n'est pas parfait non plus.
Vous pouvez utiliser un convertisseur de type (pas de vérification d'erreur):
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 termes d'organisation du code, vous pouvez créer un type de mixin qui donnerait le code suivant:
Ship ship = new Ship();
ship.SetPropertyAsString("Latitude", "5.5");
Ceci serait réalisé avec ce 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
peut être réutilisé pour différentes classes.
Vous pouvez également créer votre propre personnalisation convertisseurs de type à attacher à vos propriétés ou classes:
public class Ship : MPropertyAsStringSettable {
public Latitude Latitude { get; set; }
// ...
}
[TypeConverter(typeof(LatitudeConverter))]
public class Latitude { ... }
J'ai essayé la réponse de LBushkin et cela a bien fonctionné, mais cela ne fonctionnera pas pour les valeurs NULL et les champs Nullable. Donc je l'ai changé en ceci:
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);
}
Vous recherchez probablement la méthode Convert.ChangeType
. Par exemple:
_Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);
_
Utiliser Convert.ChangeType
et obtenir le type à convertir à partir de PropertyInfo.PropertyType
.
propertyInfo.SetValue( ship,
Convert.ChangeType( value, propertyInfo.PropertyType ),
null );
Je vais répondre à cela avec une réponse générale. Habituellement, ces réponses ne fonctionnent pas avec des guides. Voici une version de travail avec des guides aussi.
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);
Ou vous pouvez essayer:
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);
//But this will cause problems if your string value IsNullOrEmplty...
Si vous écrivez l'application Metro, vous devez utiliser un autre code:
Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetTypeInfo().GetDeclaredProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType));
Remarque:
ship.GetType().GetTypeInfo().GetDeclaredProperty("Latitude");
au lieu de
ship.GetType().GetProperty("Latitude");
L'utilisation du code suivant devrait résoudre votre problème:
item.SetProperty(prop.Name, Convert.ChangeType(item.GetProperty(prop.Name).ToString().Trim(), prop.PropertyType));