Retrieving the base definition for a PropertyInfo – .NET reflection mess

The Problem

Lets say you got a ClassA with SomeProperty and SomeMethod, plus a ClassB implementing ClassA and overriding both members.

public class ClassA
{
    public virtual bool SomeProperty
    //..

    public virtual bool SomeMethod()
    //..
}

public class ClassB : ClassA
{
    public override bool SomeProperty
    //...

    public override bool SomeMethod()
    //..
}

Now I want to reflect ClassB and find the base definition for each member.

For the virtual method, this is no problem:

typeof (ClassB).GetMethod("SomeMethod").GetBaseDefinition();

But PropertyInfo, does not offer this capability.

The Solution

I created an extension for PropertyInfo, that imitates the functionality of MethodInfo.GetBaseDefinition for properties.

Thanks, David for your suggestions (see first comment)!

public static class ReflectionExtensions
{
    /// <summary>
    /// When overridden in a derived class, returns the <see cref="propertyInfo"/> object for the 
    /// method on the direct or indirect base class in which the property represented 
    /// by this instance was first declared. 
    /// </summary>
    /// <returns>A <see cref="propertyInfo"/> object for the first implementation of this property.</returns>
    public static PropertyInfo GetBaseDefinition(this PropertyInfo propertyInfo)
    {
        var method = propertyInfo.GetAccessors(true)[0];
        if (method == null)
            return null;

        var baseMethod = method.GetBaseDefinition();

        if (baseMethod == method)
            return propertyInfo;

        var allProperties = BindingFlags.Instance | BindingFlags.Public 
            | BindingFlags.NonPublic | BindingFlags.Static;

        var arguments = propertyInfo.GetIndexParameters().Select(p => p.ParameterType).ToArray();

        return baseMethod.DeclaringType.GetProperty(propertyInfo.Name, allProperties, 
            null, propertyInfo.PropertyType, arguments, null);
    }
}

Shouldn’t be hard to create a GetBaseDefinition() for EventInfo based on this either.

.NET Reflection Library Mess

I removed this chapter, because it was based on wrong assumptions. The good news is, that the mess isn’t that big, neither 😉

3 thoughts on “Retrieving the base definition for a PropertyInfo – .NET reflection mess

  1. Why do you find it weird that GetBaseDefinition would return itself? The documentation says that it “returns the MethodInfo object for the method on the direct or indirect base class in which the method represented by this instance was first declared.” If the MethodInfo you have is the base of the virtual chain, returning itself makes perfect sense.

    The reason this might be confusing is that BaseType on the Type class behaves differently; it returns the next class up the inheritance hierarchy. In the case of Object, there is no class up the hierarchy, so it returns null. GetBaseDefinition takes a different approach; instead of going one step up the hierarchy, it goes straight to the top, even if the top is the same as where you started.

    Based on this fact, I changed the second “return null” to “return propertyInfo.” Also, the version of GetProperty being called only retrieves public members. It actually doesn’t make much sense for that version to be used in GetParentDefinition either. I changed that call to:

    return baseMethod.DeclaringType.GetProperty(propertyInfo.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, null, propertyInfo.PropertyType, propertyInfo.GetIndexParameters().Select(p => p.ParameterType).ToArray(), null);

    You can also change the null coalescing operator to “GetAccessors(true)[0]”, although that’s not necessarily a definitive improvement.

    Thanks for the code and the discussion, just what I was looking for.

  2. Hi David,

    thanks alot for your comment!

    You’re right. I didn’t get the difference between GetBase- and GetParentDefinition right. My Unit-tests where too poor, as I only checked for 2-level inheritance!

    I updated the implementation and comments according to your suggestions. Also some of my assumptions about reflection mess became obsolete.

    Again, thanks for your Feedback. It was important for me and my project!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s