Сокрытие и отражение собственности (C #) - PullRequest
21 голосов
/ 26 апреля 2010

Объявление свойства в производном классе, которое соответствует имени свойства в базовом классе, «скрывает» его (если только оно не переопределяет его с помощью ключевого слова override). Свойства как базового, так и производного класса будут возвращены Type.GetProperties(), если их типы не совпадают. Однако, если их типы do совпадают, шокирующе возвращается только свойство производного класса. Например:

class A
{
    protected double p;
    public int P { get { return (int)p; } set { p = value; } }
}
class B : A
{
    public new int P { get { return (int)p; } set { p = value; } }
}
class C : B
{
    public new float P { get { return (float)p; } set { p = value; } }
}

Вызов typeof(C).GetProperties() вернет только B.P и C.P. Можно ли назвать GetProperties() таким образом, чтобы вернуть все три? Существует почти наверняка способ сделать это путем обхода иерархии наследования, но есть ли более чистое решение?

Ответы [ 3 ]

6 голосов
/ 26 апреля 2010

GetProperties определяется как все открытые свойства типа.

Вы можете получить их методы get и set, используя:

typeof(C).GetMethods()
         .Where(m => m.Name.StartsWith("set_") || m.Name.StartsWith("get_"))

Хотя это кажется плохой идеей, по сравнению с переходом вниз по иерархии наследования для получения свойств.

5 голосов
/ 26 апреля 2010

Я не думаю, что это возможно без пересечения иерархии наследования. Впрочем, кода не должно быть слишком много:

    public static IEnumerable<PropertyInfo> GetAllProperties(Type t)
    {
        while (t != typeof(object))
        {
            foreach (var prop in t.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance))
                yield return prop;
            t = t.BaseType;
        }
    }

Конечно, если вы знаете общий базовый тип, на котором можно остановиться, вместо объекта, это будет более эффективным. Также; это займет некоторое время, чтобы сделать отражение, поэтому кешируйте результат. В конце концов, информация о типе не изменится во время выполнения.

3 голосов
/ 04 мая 2010

Благодаря отражению новое ключевое слово скрывает унаследованное свойство, только если подпись совпадает. Я думаю, что отражение соответствует подписи на средствах доступа к свойствам (get_ & set_). Это причины, по которым GetProperties() возвращает B.P и C.P, если тип возвращаемого значения отличается.

Я недавно обнаружил Fasteflect , который обеспечивает усовершенствованные механизмы отражения.

Я проверил, и Fasteflect type.Properties возвращает все дерево скрытых элементов (P). Я думаю, что API рассматривает поддержку участников (виртуальных / переопределенных) и скрытых (новых) по-разному, что хорошо для вашей «проблемы»;)

Мой тест с более быстрым ответом:

class Class1
{
    public object field1 = null;

    public virtual object Property1 { get; set; }

    public object Property2 { get; set; }

    public string Property3 { get; set; }
}

class Class2 : Class1
{
    public new object field1 = null;

    public override object Property1 { get; set; }

    public new string Property3 { get; set; }
}

class Class3 : Class2
{
    public new string Property3 { get; set; }
}

Отфильтровать поддерживающих участников, но возвращает всех скрытых членов:

typeof(Class3).Properties(Flags.ExcludeBackingMembers | Flags.Public | Flags.Instance) 
  • typeof (Class3) .Properties (Flags.ExcludeBackingMembers | Flags.Public | Flags.Instance) Count = 5 System.Collections.Generic.IList
    • [0] {System.String Property3} System.Reflection.PropertyInfo
    • [1] {System.Object Property1} System.Reflection.PropertyInfo
    • [2] {System.String Property3} System.Reflection.PropertyInfo
    • [3] {System.Object Property2} System.Reflection.PropertyInfo
    • [4] {System.String Property3} System.Reflection.PropertyInfo
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...