Подтвердить что ты не робот

Отражение частного поля из базового класса

Вот структура:

MyClass: SuperClass2

SuperClass2: SuperClass1

superClass2 находится в Product.Web и SuperClass1 в сборке .NET System.Web

Я пытаюсь заставить значение в поле private bool на SuperClass1. Но не важно, что я пытаюсь, я не могу вернуть поля из отражения.

Я использую следующий код с различными комбинациями BindingFlag, но до сих пор ничего не работало. SuperClass1 является абстрактным классом.

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

Примечания: Когда я использую GetProperties(), я получаю хороший большой список, но когда я указываю какие-либо привязки, я ничего не получаю, даже если есть соответствующие свойства. Какая сделка?

Кроме того, поле не отмечено внутренним

Obvisouly Я бы использовал GetField (имя строки, BindingFlags), но я даже не могу заставить GetFlags() работать.

Обновление. Я попытался добавить BindingFlags.Instance, как было предложено, но он не работает (как и ожидалось). Я возвращаю 2 поля, которые поступают из класса SuperClass1, наследуемого. Возвращает null при использовании с GetField (имя строки, флаги)

Вот код для базового класса. Я пытаюсь получить поле для

public abstract class BaseValidator : Label, IValidator
  {
    private bool propertiesChecked;
...
}
4b9b3361

Ответ 1

Вы можете вручную перейти в цепочку наследования, чтобы получить базовые поля:

Учитывая эти классы:

class SuperClass1
{
    private int myField;
}

class SuperClass2 : SuperClass1
{
}

class MyClass : SuperClass2
{

}

Это должно работать:

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

В этом SO-ответе есть более общее решение: Не получать поля из GetType(). GetFields с BindingFlag.Default

Ответ 2

В аналогичном ключе для решения BrokenGlass вы можете сделать это, чтобы сделать его более общим:

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

И затем:

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.");
}

Как полезный метод:

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

И затем:

Mine m = new Mine();

SetField(m, "_baseField", 10);

Ответ 3

Я думаю, вам нужно добавить флаг System.Reflection.BindingFlags.Instance. Использование | объединить его с флагом NonPublic.

EDIT:

Похоже, что у BrokenGlass все правильно. Я написал следующий быстрый тест.

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

Он правильно сообщает о поле, которое вы искали. (Тест получен из BaseValidator)

Ответ 4

Если иерархия статична, это самый простой способ:

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