2008-10-26 9 views
26

Comment obtenir la valeur d'un objet MemberInfo? .Name renvoie le nom de la variable, mais j'ai besoin de la valeur.Comment obtenir la valeur de MemberInfo?

Je pense que vous pouvez le faire avec FieldInfo mais je n'ai pas un extrait, si vous savez comment faire cela, pouvez-vous fournir un extrait ??

Merci!

Répondre

32

Voici un exemple pour les champs, en utilisant FieldInfo.GetValue:

using System; 
using System.Reflection; 

public class Test 
{ 
    // public just for the sake of a short example. 
    public int x; 

    static void Main() 
    { 
     FieldInfo field = typeof(Test).GetField("x"); 
     Test t = new Test(); 
     t.x = 10; 

     Console.WriteLine(field.GetValue(t)); 
    } 
} 

code similaire fonctionnera pour les propriétés en utilisant PropertyInfo.GetValue() - bien là, vous avez aussi besoin de transmettre les valeurs pour tous les paramètres aux propriétés. (Il n'y en aura pas pour les propriétés C# "normales", mais les indexeurs C# comptent aussi comme propriétés pour le framework.) Pour les méthodes, vous devrez appeler Invoke si vous voulez appeler la méthode et utiliser le valeur de retour.

+2

grâce jon - pourrait vous donner un exemple en commençant par un objet MemberInfo bien? –

+1

De quel genre? MemberInfos peut être des propriétés, des champs, des méthodes, des événements ou d'autres types. Vous ne pouvez pas les traiter tous de la même manière. Quelle serait la "valeur" d'un type imbriqué, par exemple? Peut-être devriez-vous nous en dire plus sur votre problème. –

+1

trop mauvais GetValue/SetValue n'étaient pas une interface qui pourrait être vérifiée contre. –

10

réponse de Jon est idéal - juste une observation: dans le cadre de la conception générale, je voudrais:

  1. généralement éviter réflexion contre membres non publiques
  2. éviter d'avoir des champs publics (presque toujours)

Le résultat de ces deux est que généralement vous avez seulement besoin de réfléchir sur les propriétés publiques (vous ne devriez pas être des méthodes d'appel à moins que vous sachiez ce qu'ils font; getters de propriété sont attendu pour être idempotent [chargement paresseux de côté]). Donc, pour PropertyInfo c'est juste prop.GetValue(obj, null);.

En fait, je suis un grand fan de System.ComponentModel, donc je serais tenté d'utiliser:

foreach(PropertyDescriptor prop in TypeDescriptor.GetProperties(obj)) 
    { 
     Console.WriteLine("{0}={1}", prop.Name, prop.GetValue(obj)); 
    } 

ou pour une propriété spécifique:

PropertyDescriptor prop = TypeDescriptor.GetProperties(obj)["SomeProperty"]; 
    Console.WriteLine("{0}={1}", prop.Name, prop.GetValue(obj)); 

Un avantage de System.ComponentModel est que fonctionnera avec des modèles de données abstraits, tels que comment un DataView expose des colonnes en tant que propriétés virtuelles; il y a aussi d'autres astuces (comme performance tricks).

+0

Cela s'est avéré très efficace pour mon scénario comme je l'ai pour travailler avec les propriétés et appeler GetField() sur l'objet renvoient un null. Merci pour cela. – MikeMalter

+0

ah, voilà ... Je ne pouvais que me rappeler vaguement qu'un autre moyen existait en dehors de l'espace de nommage Reflection: 'MemberInfo' et' PropertyInfo' .. 'PropertyDescriptor' sert bien mon objectif actuel car j'utilise' INotifyPropertyChanged' dans mon exemple... –

12

Bien que je sois généralement d'accord avec le point de vue de Marc sur le fait de ne pas refléter les champs, il y a des moments où cela est nécessaire. Si vous souhaitez refléter un membre et que cela ne vous intéresse pas qu'il s'agisse d'un champ ou d'une propriété, vous pouvez utiliser cette méthode d'extension pour obtenir la valeur (si vous voulez le type au lieu de la valeur, voir réponse this question):

public static object GetValue(this MemberInfo memberInfo, object forObject) 
    { 
     switch (memberInfo.MemberType) 
     { 
      case MemberTypes.Field: 
       return ((FieldInfo)memberInfo).GetValue(forObject); 
      case MemberTypes.Property: 
       return ((PropertyInfo)memberInfo).GetValue(forObject); 
      default: 
       throw new NotImplementedException(); 
     } 
    } 
Questions connexes