16

A string representation of an object instance property can be taken with Expression<Func<T>>:

string propertyName = ((MemberExpression) property.Body).Member.Name;

But what if I don't have (don't want to create) the instance? How do I get the property name in this case?

Explained

I need a string representation of a property name of some object.

Let's say there is an entity

public class Customer
{
    public int ID;
    public string Name;
}

Now I want to pass the key expression of this entity to some other function, thus I need the string "ID", but I don't want to hardcode the string like SomeOtherFunction("ID"), instead I use the expression SomeOtherFunction(ExpressionReader.GetString(() => CustomerInstance.ID)). For this to work I need to supply the entity instance.

Now I want to do the same without creating the instance.

net_prog
  • 9,921
  • 16
  • 55
  • 70
  • What do you mean by "the instance"? You don't need to create an instance of the class that exposes the property, but obviously you need an instance of `Expression`. – CodesInChaos Nov 15 '11 at 12:48
  • you are aware of typeof(myClass).GetProperty("abc"), right? – Efrain Nov 15 '11 at 12:51
  • What's the difference between hardcoding the ID property, and the "ID" string? – SWeko Nov 15 '11 at 13:15
  • 1
    @SWeko when there is a need to change prop name `ID` to `NewId` Visual Studio will do it for you in all referenced places :-) - maybe there are more reasons. – Michał Powaga Nov 15 '11 at 13:28
  • possible duplicate of [Get property name and type using lambda expression](http://stackoverflow.com/questions/273941/get-property-name-and-type-using-lambda-expression) – nawfal Apr 27 '13 at 15:08

5 Answers5

17

This is possible with a method signature like the following:

private static string GetPropertyName<TModel, TProperty>(Expression<Func<TModel, TProperty>> property)
{
    MemberExpression memberExpression = (MemberExpression)property.Body;

    return memberExpression.Member.Name;
}

You can call this method without an instance of the customer class:

string propertyName = GetPropertyName((Customer c) => c.ID);

Of course you should add some checks for correct expression types before you cast to MemberExpression and access memberExpression.Member.Name.

Peter
  • 3,916
  • 1
  • 22
  • 43
4

No, you dont need an instance to decompose the Expression. Even if the expression expects one, you will never invoke it.

In fact, you do it just like you did in first code snippet.

You would change you code to look like this then:

SomeOtherFunction(ExpressionReader<Customer>.GetString(c => c.ID))

Does that make sense to you?

Alternatively:

Customer c = null; // null intentionally

SomeOtherFunction(ExpressionReader.GetString(() => c.ID));

Still no problem as you are not invoking the expression.

leppie
  • 115,091
  • 17
  • 196
  • 297
  • @net_prog: You will have to modify your code, that is just 1 possible suggestion, may are possible. – leppie Nov 16 '11 at 07:51
3

With the new nameof operator of C# 6 I would suggest the following:

 private string GetNameMyProperty1(TestC c = null)
 {
     return nameof(c.MyProperty1);
 }
Malior
  • 1,221
  • 8
  • 16
  • 4
    You don't even need an instance of the object. You can just do something like `nameof(TestC.MyProperty1)` – jausel Aug 01 '17 at 19:57
1

I'm not sure I fully understand what you mean, but based on my understanding you could use Reflection. Using this approach, if you had the Type of what you wanted to get a property name from, then you could retrieve the properties using:

Type someType = typeof(SomeClass);

// Get all properties for a type
PropertyInfo[] properties = someType.GetProperties();

// Get a property from a type by it's name
PropertyInfo property = someType.GetProperty("PropertyName");

Once you have instance(s) of the PropertyInfo class, you can retrieve information such as the property name.

For more information on this approach, see the MSDN Documentation.

Samuel Slade
  • 8,405
  • 6
  • 33
  • 55
0

The selected answer is good but does not cover UnaryExpressions. It will fail when trying to get the property of a DateTime:

    private static string GetPropertyName<TModel, TProperty>(Expression<Func<TModel, TProperty>> property)
    {
        if (property.Body is MemberExpression)
        {
            return ((MemberExpression)property.Body).Member.Name;
        }
        else
        {
            var op = ((UnaryExpression)property.Body).Operand;
            return ((MemberExpression)op).Member.Name;
        }  
    }
KingOfHypocrites
  • 9,316
  • 9
  • 47
  • 69