Подтвердить что ты не робот

Скрытие и отражение собственности (С#)

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

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() таким образом, чтобы он возвращал все три? Существует почти наверняка способ сделать это, пройдя иерархию наследования, но есть ли более чистое решение?

4b9b3361

Ответ 1

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

Вы можете получить их методы получения и установки, используя:

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

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

Ответ 2

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

    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

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

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

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

Мой тест с быстрым отражением:

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(флаги .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