Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reflection: inconsistent framework behavior with GetRuntimeProperty methods

When playing around with reflection in the new .NET Framework 4.5, I encountered a strange behavior that I found quite unexpected. The namespace System.Reflection provides some new extension methods for exploiting Type objects. Two of those are GetRuntimeProperty(string name) and GetRuntimeProperties().

Now imagine that you have a simple object with an internal property.

public class ObjectBase
{
    protected int Id { get; set; }
    public string Name { get; set; }
}

And you now try to exploit this type.

var properties = typeof(ObjectBase).GetRuntimeProperties();
// properties.Count = 2

var idProperty = typeof(ObjectBase).GetRuntimeProperty("Id");
var nameProperty = typeof(ObjectBase).GetRuntimeProperty("Name");
// idProperty = null
// nameProperty = System.String Name

As expected the properties object holds two property definition for the Id and Name property defintions and the nameProperty holds the Name property definition. What was not expected was the idProperty object to be null...

Coming from the .NET Framework, I guess this was intended by Microsoft architects but I must say it does not seem like something you would really expect to happen. I do believe such similar methods should behave the same but it seems that GetRuntimeProperty filters on public properties where GetRuntimeProperties apply no filters.

Does anybody have a reasonable explanation on why do Microsoft decided that those similar methods should have different behaviors? A design error?

Thanks.

like image 651
Ucodia Avatar asked Dec 22 '12 15:12

Ucodia


1 Answers

Internally GetRuntimeProperty calls Type.GetProperty(name) which searches for the public property with the specified name. Property Id is protected, thus it cannot be found.

public static PropertyInfo GetRuntimeProperty(this Type type, string name)
{
    CheckAndThrow(type);
    return type.GetProperty(name);
}

On the other hand GetRuntimeProperties returns both public and non-public properties

public static IEnumerable<PropertyInfo> GetRuntimeProperties(this Type type)
{
    CheckAndThrow(type);
    return type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public |
                              BindingFlags.Static | BindingFlags.Instance);
}

Explanation: GetRuntimeProperties purpose is returning IEnumerable<PropertyInfo> collection of all properties, leaving you with filtering that collection via LINQ. You can select public, non-public or any other type of properties. With single property returned by GetRuntimeProperty you don't need that flexibility, thus it is restricted for most common usage.

like image 56
Sergey Berezovskiy Avatar answered Nov 13 '22 05:11

Sergey Berezovskiy