Страницы

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

воскресенье, 22 декабря 2019 г.

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

#c_sharp


Есть вот такая конструкция, напишу упрощённо:

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, а у него естественно их нет, они есть только у А.

Как сделать так, чтобы метод отрабатывал корректно в обоих случаях?
    


Ответы

Ответ 1



Проблема в том, что метод 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(); }

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

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