Отражение частного поля из базового класса
Вот структура:
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;
...
}
Ответы
Ответ 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);