Question

Je voudrais définir une propriété d'un objet par la réflexion, avec une valeur de type string. Ainsi, par exemple, supposons que j'ai une classe Ship, avec une propriété de Latitude, qui est un double.

Voici ce que je voudrais faire:

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

Comme, cela jette un ArgumentException:

  

Objet de type 'System.String' ne peut pas être convertie en type 'System.Double'.

Comment puis-je convertir la valeur du bon type, basé sur propertyInfo?

Était-ce utile?

La solution

Vous pouvez utiliser Convert.ChangeType() - Il vous permet d'utiliser les informations d'exécution sur tout type de IConvertible pour modifier les formats de représentation. Toutes les conversions ne sont possibles, cependant, et vous pouvez avoir besoin d'écrire une logique de cas particulier si vous voulez soutenir les conversions de types qui ne sont pas IConvertible.

Le code correspondant (sans manipulation d'exception ou de la 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);

Autres conseils

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 de regarder l'ensemble Convert classe .

Cette classe, et bien d'autres classes utiles font partie du System Namespace . Je trouve qu'il est utile pour analyser cet espace chaque année ou pour voir quelles sont les caractéristiques que je l'ai manqué. Faites un essai!

Je remarque que beaucoup de gens recommandent Convert.ChangeType - Cela fonctionne pour certains cas, cependant, dès que vous commencez impliquant les types nullable vous commencerez à recevoir InvalidCastExceptions:

  

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

Une enveloppe a été écrit il y a quelques années pour gérer cela, mais ce n'est pas parfait non plus.

  

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

Vous pouvez utiliser un convertisseur de type (pas de contrôle 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 ce qui concerne l'organisation du code, vous pouvez créer un de type de mixin qui résulterait dans le code comme ceci:

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

Ce serait atteint 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ée pour de nombreuses classes différentes.

Vous pouvez également créer votre propre coutume convertisseurs de type pour fixer à vos biens ou catégories:

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

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

J'ai essayé la réponse de LBushkin et il a très bien fonctionné, mais il ne fonctionnera pas pour les valeurs nulles et les champs nullable. J'ai donc changé à 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 êtes 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);

Utilisation Convert.ChangeType et obtenir le type de convertir de la PropertyInfo.PropertyType.

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

Je répondrai à cela avec une réponse générale. Habituellement, ces réponses ne fonctionne pas avec GUIDs. Voici une version de travail avec GUIDs 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));

Note:

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

au lieu de

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

En utilisant le code suivant devrait résoudre votre problème:

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

Vous cherchez à jouer avec la réflexion ou vous cherchez à construire un logiciel de production? Je me demande pourquoi vous utilisez la réflexion pour définir une propriété.

Double new_latitude;

Double.TryParse (value, out new_latitude);
ship.Latitude = new_latitude;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top