88 votes

'casting' avec reflet

Considérez l'exemple de code suivant:

 class SampleClass
{
    public long SomeProperty { get; set; }
}

public void SetValue(SampleClass instance, decimal value)
{
    // value is of type decimal, but is in reality a natural number => cast
    instance.SomeProperty = (long)value;
}
 

Maintenant, je dois faire quelque chose de similaire par la réflexion:

 void SetValue(PropertyInfo info, object instance, object value)
{
    // throws System.ArgumentException: Decimal can not be converted to Int64
    info.SetValue(instance, value)  
}
 

Notez que je ne peux pas supposer que le PropertyInfo représente toujours un long, ni cette valeur est toujours un nombre décimal. Cependant, je sais que cette valeur peut être convertie dans le type correct pour cette propriété.

Comment puis-je convertir le paramètre 'value' au type représenté par l'instance de PropertyInfo par réflexion?

144voto

Thomas Levesque Points 141081
void SetValue(PropertyInfo info, object instance, object value)
{
    info.SetValue(instance, Convert.ChangeType(value, info.PropertyType));
}

44voto

jeroenh Points 12777

La réponse de Thomas est correcte, mais je pensais pouvoir ajouter que Const.ChangeType ne gère pas la conversion en types nullable. Pour gérer les types nullables, j'ai utilisé le code suivant:

 void SetValue(PropertyInfo info, object instance, object value)
{
    var targetType = info.PropertyType.IsNullableType() 
         ? Nullable.GetUnderlyingType(info.PropertyType) 
         : info.PropertyType; 
    var convertedValue = Convert.ChangeType(value, targetType);

    info.SetValue(instance, convertedValue, null);
}
 

Ce code utilise la méthode d'extension suivante:

 public static class TypeExtensions
{
  public static bool IsNullableType(this Type type)
  {
    return type.IsGenericType 
    && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>));
  }
 

10voto

Ignacio Calvo Points 336

En contribuant à la réponse de jeroenh, j'ajouterais que Convert.ChangeType se bloque avec une valeur null, la ligne permettant d'obtenir la valeur convertie doit donc être:

 var convertedValue = value == null ? null : Convert.ChangeType(value, targetType);
 

2voto

Loukas Points 223

Lorsque le type est un Guid Nullable, aucune des solutions proposées ci-dessus ne fonctionne. La distribution non valide de ' System.DBNull ' à ' System.Guid ' est levée à Convert.ChangeType

Pour corriger ce changement, procédez comme suit:

 var convertedValue = value == System.DBNull.Value ? null : Convert.ChangeType(value, targetType);
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X