How to get a property name of a given type strongly typed?

.net c# expression-trees reflection

Question

I would like to be able to retrieve the name of a property of a type using a strongly typed syntax. I already got a function to get a property name of an instance:

public static string PropertyName<T, TReturn>(this T obj, Expression<Func<T, TReturn>> property) where T : class 
{
    MemberExpression body = (MemberExpression) property.Body;
    if (body == null) throw new ArgumentException("The provided expression did not point to a property.");       
    return body.Member.Name;
}

Which can be called like this:

Car car = new Car();
car.PropertyName(x => x.Wheels) //returns "Wheels"

I'm trying to create another function that could support the following:

Type t = Typeof(Car);
t.PropertyName(x => x.Wheels) //should return "Wheels"

Or just (even better!):

Car.PropertyName(x => x.Wheels)

How would I go about this?

Accepted Answer

You can rewrite your method to use it without creating an instance:

var prop = ReflectionHelper.PropertyName<Car>(x => x.Wheels);

because your don't use obj inside because you don't need it:

public static class ReflectionHelper
{
    public static string PropertyName<T>(Expression<Func<T, object>> property) where T : class 
    {
        MemberExpression body = (MemberExpression)property.Body;
        return body.Member.Name;
    }
}

Note that the return type doesn't have to be strongly-typed, it can be just object.


Popular Answer

@abatishchev example only works if Wheels is a reference type.

If you have the following

public class Car
{
   public int ID;
}

And you try to call this

var prop = ReflectionHelper.PropertyName<Car>(x => x.ID);

You'll get the following exception

InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.UnaryExpression' to type 'System.Linq.Expressions.MemberExpression'.

I think this has to do with the fact that you are passing a value type to the expression, so it has to be boxed into an object. If you pass a reference type, it doesn't need to be boxed to object.

What you can do instead is this:

var prop = ReflectionHelper.PropertyName((Car x) => x.Wheels);

public static class ReflectionHelper
{
    public static string PropertyName<T, P>(Expression<Func<T, P>> property) 
        where T : class 
    {
        MemberExpression body = (MemberExpression)property.Body;
        return body.Member.Name;
    }
}


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why