Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I determine if a property was overridden?

I am doing a project that where I need to register all the properties, because of the system being so huge it would require a lot of work to register all the properties that i want to be dependent for the purpose of Xaml.

The goal is to find all properties that are on the top of the tree.

so basically

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; }
}

The end result would be something like this

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

If you notice I don't want to accept overridden properties because of the way I search for the properties if I do something like this

C.Property3 for example and it cannot find it it will check C's basetype and there it will find it.

This is what I have so far.

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
        }
    }
}

What I want are the following:

  • Public properties, that are not overridden, not static, not private
  • Either get and set properties are allowed
  • They are not an array or a generic type
  • They are the top of the tree ie C class in the example is the highest (The property list example is exactly what I am looking for)
  • They are not an indexer property ( this[index] )
like image 370
Benjamin Avatar asked Dec 22 '10 00:12

Benjamin


2 Answers

In order to ignore inherited members, you can use the BindingFlags.DeclaredOnly flag, which you're already doing.

But when properties are overridden, they are re-declared by the derived class. The trick is to then look at their accessor methods to determine if they are in fact overridden.

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);
    }
}

If the property is overridden, its 'getter' MethodInfo will return a different MethodInfo from GetBaseDefinition.

like image 55
Josh Avatar answered Oct 19 '22 11:10

Josh


None of these solutions worked well in my case. I ended up using DeclaringType to determine difference in definitions (I've provided the full function to give some context):

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));
            }
        }
    }
like image 2
Stuart Gillibrand Avatar answered Oct 19 '22 11:10

Stuart Gillibrand