2

I have a property in Myclass:

public class MyClass{    
    public string FirstName {get;set;}
}

How can I get the PropertyInfo (using GetProperty("FirstName")) without a string?

Today I use this:

PropertyInfo propertyTitleNews = typeof(MyClass).GetProperty("FirstName");

Is there a way for use like this:

PropertyInfo propertyTitleNews = typeof(MyClass).GetProperty(MyClass.FirstName);

?

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
  • 1
    Seems like if you had access to the properties of the class like that you wouldn't need reflection to begin with. If this is .NET 4 or later, have you tried using the Dynamic keyword? – Parrish Husband Nov 09 '13 at 22:09
  • 1
    Yes, it is possible. [look at this answer](http://stackoverflow.com/a/17049349/1082327). – Arian Motamedi Nov 09 '13 at 22:10
  • I agree with Locke. It doesn't make much sense. You usually use reflection when you the only way to create a property is from string. – Szymon Nov 09 '13 at 22:12
  • @Szymon No, in general it does make sense as `PropertyInfo` has more information than only property's type and its value. – BartoszKP Nov 09 '13 at 22:26
  • Beware of all answers that deals with member expressions. There is a tripping corner case: http://stackoverflow.com/questions/6658669/lambda-expression-not-returning-expected-memberinfo ! Not a very safe thing to do – nawfal Dec 13 '13 at 09:48

3 Answers3

6

See here. The idea is to use Expression Trees.

public static string GetPropertyName<T, TReturn>(Expression<Func<T, TReturn>> expression)
{
    MemberExpression body = (MemberExpression)expression.Body;
    return body.Member.Name;
}

And then use it like:

var name = GetPropertyName<MyClass, string>(c => c.FirstName);

A bit cleaner solution would be if one would not required to specify so much generic parameters. And it is possible via moving MyClass generic param to util class:

public static class TypeMember<T>
{
    public static string GetPropertyName<TReturn>(Expression<Func<T, TReturn>> expression)
    {
        MemberExpression body = (MemberExpression)expression.Body;
        return body.Member.Name;
    }
}

Then usage will be cleaner:

var name = TypeMember<MyClass>.GetPropertyName(c => c.FirstName);
Ivan Danilov
  • 14,287
  • 6
  • 48
  • 66
  • Is it possible to do this without the overhead of lambda? – rollsch May 16 '18 at 08:10
  • @rolls what overhead do you mean? The lambda isn't _executed_ ever, so it is just a data passed by the compiler. The lambda doesn't capture any locals either, so there are no additional allocations as well. – Ivan Danilov Jul 13 '18 at 16:49
  • Good point. I didn't think about it in that level of detail, it is not much different to passing in an object/struct really. – rollsch Jul 16 '18 at 01:17
3

Another possibility, beside Ivan Danilov's answer, is to provide an extension method:

public static class PropertyInfoExtensions
{
    public static string GetPropertyName<TType, TReturnType>(
        this TType @this,
        Expression<Func<TType, TReturnType>> propertyId)
    {
        return ((MemberExpression)propertyId.Body).Member.Name;
    }
}

And then use it like this:

MyClass c;
PropertyInfo propertyTitleNews = c.GetPropertyName(x => x.FirstName);

The drawback is that you need an instance, but an advantage is that you don't need to supply generic arguments.

Community
  • 1
  • 1
BartoszKP
  • 34,786
  • 15
  • 102
  • 130
2

You could do that

var property = ExpressionExtensions.GetProperty<MyClass>(o => o.FirstName);

With this helper :

public static PropertyInfo GetProperty<T>(Expression<Func<T, Object>> expression)
{
     MemberExpression body = (MemberExpression)expression.Body;
     return typeof(T).GetProperty(body.Member.Name);
}
Damien
  • 8,889
  • 3
  • 32
  • 40