#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 ListSelectllControlsByType(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(); }
Комментариев нет:
Отправить комментарий