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