Как определить, было ли переопределено свойство? - PullRequest
10 голосов
/ 22 декабря 2010

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

Цель состоит в том, чтобы найти все свойства, которые находятся в верхней части дерева.

, поэтому в основном

public class A{
    public int Property1 { get; set; }
}

public class B : A{
    public int Property2 { get; set; }
    public virtual int Property3 { get; set; }
}

public class C : B{
    public override int Property3 { get; set; }
    public int Property4 { get; set; }
    public int Property5 { get; set; }
}

Конечный результат будет выглядеть примерно так

A.Property1  
B.Property2  
B.Property3  
C.Property4  
C.Property5  

Если вы заметили, что я не хочу принимать переопределенные свойства из-за того, как я ищу свойства, если я делаю что-то вроде

C.Property3, например, и не может найти его, он будетпроверьте базовый тип C и там он найдет его.

Это то, что у меня есть до сих пор.

public static void RegisterType( Type type )
{
    PropertyInfo[] properties = type.GetProperties( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.GetProperty | BindingFlags.SetProperty );

    if ( properties != null && properties.Length > 0 )
    {
        foreach ( PropertyInfo property in properties )
        {
            // if the property is an indexers then we ignore them
            if ( property.Name == "Item" && property.GetIndexParameters().Length > 0 )
                continue;

            // We don't want Arrays or Generic Property Types
            if ( (property.PropertyType.IsArray || property.PropertyType.IsGenericType) )
                continue;

            // Register Property
        }
    }
}

Мне нужно следующее:

  • Publicсвойства, которые не переопределены, не статические, не частные
  • Любые свойства get и set разрешены
  • Они не массив или универсальный тип
  • Это вершина дерева, т. Е. Класс C в этом примере самый высокий (пример списка свойств - именно то, что я ищу)
  • Они , а не свойство индексатора (этот [индекс])

Ответы [ 3 ]

22 голосов
/ 22 декабря 2010

Чтобы игнорировать унаследованные члены, вы можете использовать флаг BindingFlags.DeclaredOnly, который вы уже делаете.

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

Type type = typeof(Foo);

foreach ( var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
    var getMethod = property.GetGetMethod(false);
    if (getMethod.GetBaseDefinition() == getMethod) {
        Console.WriteLine(getMethod);
    }
}

Если свойство переопределено, его MethodInfo 'получателя' вернет другое MethodInfo из GetBaseDefinition.

2 голосов
/ 02 июля 2014

Ни одно из этих решений не сработало в моем случае.В итоге я использовал DeclaringType для определения различий в определениях (я предоставил полную функцию для определения контекста):

static public String GetExpandedInfo(Exception e)
{
    StringBuilder info = new StringBuilder();
    Type exceptionType = e.GetType();

    // only get properties declared in this type (i.e. not inherited from System.Exception)
    PropertyInfo[] propertyInfo = exceptionType.GetProperties(System.Reflection.BindingFlags.DeclaredOnly | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
    if (propertyInfo.Length > 0)
    {
        // add the exception class name at the top
        info.AppendFormat("[{0}]\n", exceptionType.Name);

        foreach (PropertyInfo prop in propertyInfo)
        {
            // check the property isn't overriding a System.Exception property (i.e. Message)
            // as that is a default property accessible via the generic Exception class handlers
            var getMethod = prop.GetGetMethod(false);
            if (getMethod.GetBaseDefinition().DeclaringType == getMethod.DeclaringType)
            {
                // add the property name and it's value
                info.AppendFormat("{0}: {1}\n", prop.Name, prop.GetValue(e, null));
            }
        }
    }
0 голосов
/ 22 декабря 2010

Вы можете использовать property.DeclaringType, чтобы проверить, какой тип объявил свойство.Если он отличается от типа, над которым вы сейчас размышляете, он переопределяется.

Было отмечено, что переопределяющий тип переопределит свойство.Не думал об этом.Я предполагаю, что вы должны пройти через базовые типы, чтобы увидеть, объявили ли они свойство с тем же именем.Тогда, если он объявлен в отраженном типе И базовым классом, он будет переопределен?

О, Джош уже указал на это ...: -)

...