2009-03-26 2 views
17

Je suis un novice absolu à la réflexion en C#. Je veux utiliser la réflexion pour accéder à tous les champs privés d'une classe, y compris ceux qui sont hérités.C#: Accès aux membres d'instance privée hérités par réflexion

J'ai réussi à accéder à tous les champs privés à l'exclusion de ceux qui sont hérités, ainsi que de tous les champs hérités publics et protégés. Cependant, je n'ai pas pu accéder aux champs privés hérités. L'exemple suivant illustre:

class A 
{ 
    private string a; 
    public string c; 
    protected string d; 
} 

class B : A 
{ 
    private string b; 
} 

class test 
{ 
    public static void Main(string[] Args) 
    { 
     B b = new B();  
     Type t; 
     t = b.GetType(); 
     FieldInfo[] fields = t.GetFields(BindingFlags.Public | BindingFlags.NonPublic 
             | BindingFlags.Instance); 
     foreach(FieldInfo fi in fields){ 
      Console.WriteLine(fi.Name); 
     } 
     Console.ReadLine(); 
    } 
} 

Ceci ne parvient pas à trouver le champ B.a.

Est-il même possible d'accomplir cela? La solution évidente serait de convertir les champs hérités privés en champs protégés. Ceci, cependant, est hors de mon contrôle pour le moment.

Répondre

14

Comme Lee l'a déclaré, vous pouvez le faire avec la récursivité.

private static void FindFields(ICollection<FieldInfo> fields, Type t) { 
    var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; 

    foreach (var field in t.GetFields(flags)) { 
     // Ignore inherited fields. 
     if (field.DeclaringType == t) 
      fields.Add(field); 
    } 

    var baseType = t.BaseType; 
    if (baseType != null) 
     FindFields(fields, baseType); 
} 

public static void Main() { 
    var fields = new Collection<FieldInfo>(); 
    FindFields(fields, typeof(B)); 
    foreach (FieldInfo fi in fields) 
     Console.WriteLine(fi.DeclaringType.Name + " - " + fi.Name); 
} 
+0

Au lieu de la clause "if" pour ignorer les champs hérités, vous pouvez simplement spécifier BindingFlags.DeclaredOnly. – Timwi

+0

sans utiliser BaseType sur un type, pouvons-nous toujours accéder au membre privé de la classe de base. Non, cela ne résout aucun problème réel pour moi, mais je suis simplement curieux car en utilisant la propriété BaseType de la classe Type je suis convaincu que (en l'écrivant) j'accède aux membres de la classe de base Childs, donc il n'y a pas moyen d'utiliser Propriété BaseType pour atteindre la même chose? – Zenwalker

0

Vous ne pouvez pas accéder aux champs privés de A en utilisant le type de B car ces champs n'existent pas dans B - ils existent seulement dans A. Vous devez soit spécifier le type de A directement, soit le récupérer par d'autres moyens (par exemple, obtenir la classe de base du type B).

+3

Très mauvais, bien sûr, ils existent dans B. Si elles ne sont pas en B, comment une méthode pourrait héritée de A qui accède à un tel travail sur le terrain privé ? – Timwi

+4

L'instance de B peut avoir des membres privés de A, mais le type de B n'a aucune connaissance de ces membres. – Andy

4

Je ne l'ai pas essayé, mais vous devriez pouvoir accéder aux membres privés de type de base à travers la propriété Type.BaseType et accumuler récursivement tous les champs privés à travers la hiérarchie d'héritage.

-1

Vous pouvez accéder aux membres privés de la classe A de la classe B avec 'classes emboîtées' . Vous faites de classe A comme externe de classe et de classe B comme classe interne

Class A 
{ 
... 
Class B 
{ 
....... 
    } 

} 
+2

Je ne suis pas en mesure de modifier les classes. J'essaie juste de recueillir des informations à leur sujet via la réflexion. – Odrade