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"
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
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)
1