Страницы

Поиск по вопросам

среда, 14 ноября 2018 г.

Доступ к полям родительского класса (Рефлексия) - C#

Есть вот такая конструкция, напишу упрощённо:
public partial class A : UserControl {
public class B : A {}
public A(){ var cmbList = C.SelectllControlsByType(this, typeof(ComboBox)); } }
public static class C { ///

/// Выбрать контролы заданого типа /// /// /// private static List SelectllControlsByType(Control rootControl, Type selectionControlType) { return (from field in rootControl.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance) where field.FieldType == selectionControlType select field.GetValue(rootControl) as Control).ToList(); } }
Если инстанциируем контрол класса A, то метод SelectllControlsByType отрабатывает корректно и возвращает (к примеру) список из трёх комбобоксов, которые есть на этом контроле. А если создаем тот же контрол, но через дочерний класс: new A.B(), то метод возвращает пустой список, хотя комбобоксы по прежнему существуют на этом контроле.
Т.е. я так понимаю GetType().GetFields в методе SelectllControlsByType пытаются взять поля класса B, а у него естественно их нет, они есть только у А
Как сделать так, чтобы метод отрабатывал корректно в обоих случаях?


Ответ

Проблема в том, что метод GetFields возвращает закрытые поля лишь текущего класса, но не базовых классов. Поэтому вы закономерно получаете (пустой) список полей класса B.A
Вам нужно подняться вверх по дереву наследования:
static List SelectllControlsByType(Control rootControl, Type selectionControlType) { IEnumerable GetTypeChain(Type from, Type to) { for (var t = from; t != to; t = t.BaseType) yield return t; }
IEnumerable GetPrivateFields(Type t) => t.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
var allFields = GetTypeChain(rootControl.GetType(), typeof(Control)) .SelectMany(GetPrivateFields);
return (from field in allFields where field.FieldType == selectionControlType select field.GetValue(rootControl) as Control).ToList(); }

Комментариев нет:

Отправить комментарий