2009-03-26 21 views
17

Sono un principiante assoluto alla riflessione in C#. Voglio usare reflection per accedere a tutti i campi privati ​​di una classe, compresi quelli che sono ereditati.C#: accesso ai membri di istanze private ereditate tramite Riflessione

Sono riuscito ad accedere a tutti i campi privati, esclusi quelli che sono ereditati, così come tutti i campi ereditati pubblici e protetti. Tuttavia, non sono stato in grado di accedere ai campi privati ​​ereditati. Il seguente esempio illustra:

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(); 
    } 
} 

Questo non riesce a trovare il campo B.a.

È persino possibile eseguire questo? La soluzione ovvia sarebbe convertire i campi privati ​​ereditati in campi protetti. Questo, tuttavia, è fuori dal mio controllo al momento.

risposta

14

Come affermato da Lee, è possibile farlo con la ricorsione.

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

Invece della clausola "if" per ignorare i campi ereditati, è sufficiente specificare BindingFlags.DeclaredOnly. – Timwi

+0

con fuori utilizzando BaseType su un tipo, possiamo ancora accedere al membro privato della classe Base. No, non sto risolvendo alcun problema del mondo reale per me, ma sono solo curioso perché usando la proprietà BaseType della classe Type sono convinto che (mentre lo scrivo) sto accedendo ai membri della classe base di Childs, quindi c'è un altro modo senza usare Proprietà BaseType per ottenere lo stesso risultato? – Zenwalker

0

Non è possibile accedere ai campi privati ​​della A utilizzando il tipo di B perché quei campi non esistono in B - esistono solo in A. È necessario specificare direttamente il tipo di A oppure recuperarlo tramite altri mezzi (come ottenere la classe base dal tipo di B).

+3

Spazzatura, naturalmente esistono in B. Se non erano in B, come potrebbe un metodo ereditato da A che accede a un tale lavoro sul campo privato ? – Timwi

+4

L'istanza di B può avere membri privati ​​di A, ma il Tipo di B non ha conoscenza di tali membri. – Andy

4

Non l'ho provato, ma dovresti essere in grado di accedere al tipo di base membri privati ​​tramite la proprietà Type.BaseType e accumulare ricorsivamente tutti i campi privati ​​attraverso la gerarchia dell'ereditarietà.

-1

È possibile accedere ai membri privati ​​di classe A dalla classe B con 'classi nidificate' . Fate Classe A come esterno Classe A e Classe B come classe interna

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

} 
+2

Non riesco a modificare le classi. Sto solo cercando di raccogliere informazioni su di loro tramite la riflessione. – Odrade

Problemi correlati