2011-08-05 17 views
19

Oto struktura:Zastanawiając prywatną pole z klasy bazowej

MojaKlasa: SuperClass2

SuperClass2: SuperClass1

superClass2 jest w Product.Web i SuperClass1 jest w .NET system.Web złożenie

Próbuję wymusić wartość w prywatnym bool polu na SuperClass1. Ale nieważne, co próbuję, nie mogę uzyskać pól, które powrócą z refleksji.

Korzystam z następującego kodu z różnymi kombinacjami BindingFlag, ale nic nie zadziałało do tej pory. SuperClass1 to klasa abstrakcyjna.

((SuperClass1)this).GetType().GetFields(System.Reflection.BindingFlags.NonPublic); 

Uwagi: Gdy używam GetProperties() wrócę ładne, duże liście, ale kiedy określił BindingFlags mam nic, chociaż istnieją właściwości dopasowania. O co chodzi?

Ponadto, pole nie jest zaznaczone wewnętrzny

obvisouly będę używając GetField (String name, BindingFlags), ale nie można nawet dostać GetFlags() do pracy.

Aktualizacja: Próbowałem dodanie BindingFlags.Instance jak sugeruje ale to nie działa (zgodnie z oczekiwaniami w każdym razie). Wracam 2 pola, które pochodzą z klasy SuperClass1 dziedziczy po. Zwraca null gdy używana z GetField (nazwy strun, flagi)

Oto kod dla klasy bazowej próbuję uzyskać pole do

public abstract class BaseValidator : Label, IValidator 
    { 
    private bool propertiesChecked; 
... 
} 
+0

Przepraszam za głupie pytanie, ale dlaczego to robisz? :) – sll

+2

Świetne pytanie. Z powodu Product.Web.SuperClass2, muszę to zrobić jako pracę, aby zaimplementować obsługę funkcji, którą powinny już obsługiwać, ale nie. Zasadniczo API ma metodę wirtualną, ale ZAWSZE wywołuje podstawową implementację. Muszę więc zmienić wartość pola, aby nie wykonywał pewnych testów, więc mogę uruchomić mój kod. –

+1

Proszę nie pytać "dlaczego chcesz to zrobić?" - nie jest to pomocne ani konstruktywne - istnieje milion ważnych powodów, aby to zrobić, a wszystkie są inne. Oczywiście kod pachnie, ale dogmat nie pomoże 900 tysiącom nas, którzy zostaną wyrzuceni tutaj przez google. – BrainSlugs83

Odpowiedz

30

Można ręcznie idą w górę w łańcuchu dziedziczenia dostać pola podstawy:

Podane tych klas:

class SuperClass1 
{ 
    private int myField; 
} 

class SuperClass2 : SuperClass1 
{ 
} 

class MyClass : SuperClass2 
{ 

} 

To powinno działać:

var myObj = new MyClass(); 
var myField = typeof(MyClass).BaseType 
          .BaseType 
          .GetField("myField", BindingFlags.Instance | BindingFlags.NonPublic); 

Jest bardziej ogólne rozwiązanie w tej odpowiedzi SO: Not getting fields from GetType().GetFields with BindingFlag.Default

+0

To się udało. Nie widziałem tam BaseType. Miejmy nadzieję, że ta przygoda rozwiąże mój pierwotny problem ... –

3

myślę, że trzeba dodać System.Reflection Flaga .BindingFlags.Instance. Użyj | połączyć go z flagą NonPublic.

EDIT:

Wygląda BrokenGlass ma rację. Napisałem następujący szybki test.

var fields = test.GetType().BaseType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic); 
foreach (var field in fields) 
{ 
    System.Console.WriteLine(field.Name); 
} 

Poprawnie zgłasza szukane pole.(Test pochodzi z BaseValidator)

+0

Próbowałem już tego. –

+0

Istnieje pozwolenie, które musisz posiadać, aby odzwierciedlić prywatne pola. Czy możesz podać pole, do którego próbujesz uzyskać dostęp, i klasę, z której czerpieś w System.Web? (Na pewno będziesz potrzebował flagi instancji, aby to działało). – Nathanael

+0

"System.Web.UI.WebControls.BaseValidator" i chcę ustawić właściwości Sprawdzono –

7

W podobny sposób do rozwiązania BrokenGlass jest, można to zrobić, aby uczynić go nieco bardziej ogólna:

class Base { private int _baseField; } 
class Derived : Base { } 
class Mine : Derived { } 

, a następnie:

Type t = typeof(Mine); 
FieldInfo fi = null; 

while (t != null) 
{ 
    fi = t.GetField("_baseField", BindingFlags.Instance | BindingFlags.NonPublic); 

    if (fi != null) break; 

    t = t.BaseType; 
} 

if (fi == null) 
{ 
    throw new Exception("Field '_baseField' not found in type hierarchy."); 
} 

Jako sposób użytkowy:

public static void SetField(object target, string fieldName, object value) 
{ 
    if (target == null) 
    { 
     throw new ArgumentNullException("target", "The assignment target cannot be null."); 
    } 

    if (string.IsNullOrEmpty(fieldName)) 
    { 
     throw new ArgumentException("fieldName", "The field name cannot be null or empty."); 
    } 

    Type t = target.GetType(); 
    FieldInfo fi = null; 

    while (t != null) 
    { 
     fi = t.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic); 

     if (fi != null) break; 

     t = t.BaseType; 
    } 

    if (fi == null) 
    { 
     throw new Exception(string.Format("Field '{0}' not found in type hierarchy.", fieldName)); 
    } 

    fi.SetValue(target, value); 
} 

A następnie:

Mine m = new Mine(); 

SetField(m, "_baseField", 10); 
0

Jeśli hierarchia jest statyczna, najprostszym sposobem, aby to zrobić: sposób

var field = typeof(SuperClass1).GetField("_privateBaseField",System.Reflection.BindingFlags.NonPublic); 
0

rozszerzenia:

/// <summary> 
/// Includes private fields in base classes of 't' (unlike 'System.Type.GetField') 
/// </summary> 
public static FieldInfo GetPrivateField(this Type t, String name) 
{ 
    FieldInfo fi; 
    do 
     if ((fi = t.GetField(name, BindingFlags.Instance | 
            BindingFlags.NonPublic | 
            BindingFlags.DeclaredOnly)) != null) 
      return fi; 
    while ((t = t.BaseType) != null); 
    return null; 
} 
Powiązane problemy