0

I want to increase the maintainability by passing a delegate rather than a const string. What I've done is like this;

var propertyName = SprintMetrics.GetNameOf(metric => metric.Productivity); //Should be : "Productivity"

and:

public static string GetNameOf(Func<SprintMetrics, double> valueFunc)
{
    return valueFunc.GetMethodInfo().Name; //Result is : <Excute>b_40....
}

During the debug, I walked throw "valueFunc", and there was no "Productivity" anywhere.

Is there any way to get the property's name "Productivity"? Thanks.


According to Access Denied's answer below, it can be done by both of the following:

var p = nameof(SprintMetrics.Productivity); //"Productivity"

var metrics = new SprintMetrics();
p = nameof(metrics.Productivity); //"Productivity"
cheny
  • 2,545
  • 1
  • 24
  • 30

2 Answers2

2

I walked throw "valueFunc", and there was no "Productivity" anywhere.

That's because valueFunc is simply an anonymous function that returns the value of the Productivity property since that's how you defined the delegate.

If instead you want to inspect the delegate then use Expression instead:

public static string GetNameOf<T>(Expression<Func<SprintMetrics, T>> valueFunc)
{
    var expression = (MemberExpression)valueFunc.Body;
    return expression.Member.Name;
}

Of course, you'll want to add error handling (what if action.Body is not a MemberExpression? What if it refers to a field and not a property?). You can see a more complete example in this answer

D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • Thanks a lot for the tip! I would study more about the expression things :) There would be much to explore! – cheny Sep 08 '18 at 06:46
1

You can use C# keyword nameof which was designed for this task:

var propertyName = nameof(metric.Productivity)

For more info take a look at the following article.

As for your code in order to extract property name from lambda expressions you can use the following method (And there is no need to have input Func parameter in that case):

public static string GetPropertyName<TProperty>(Expression<Func<TProperty>> propertyLambda)
{
    MemberExpression member = propertyLambda.Body as MemberExpression;
    if (member == null)
        throw new ArgumentException(string.Format(
            "Expression '{0}' refers to a method, not a property.",
            propertyLambda.ToString()));

    PropertyInfo propInfo = member.Member as PropertyInfo;
    if (propInfo == null)
        throw new ArgumentException(string.Format(
            "Expression '{0}' refers to a field, not a property.",
            propertyLambda.ToString()));
    return propInfo.Name;
}

And you can call it this way: GetPropertyName(() => metric.Productivity)

Access Denied
  • 8,723
  • 4
  • 42
  • 72