Problem
(See below for the solution I came up with based on the answer I accepted.)
I’m attempting to improve the maintainability of some reflection-based programmes. The app contains a.NET Remoting interface that exposes a method called Execute for accessing areas of the app that aren’t accessible through the published remote interface.
Here’s how the app designates attributes (in this case, a static one) that should be accessed via Execute:
RemoteMgr.ExposeProperty("SomeSecret", typeof(SomeClass), "SomeProperty");
As an example, a remote user could dial:
string response = remoteObject.Execute("SomeSecret");
and the app would look for SomeClass through reflection. Return the value of SomeProperty as a string.
Unfortunately, this approach is broken if SomeoneRenamesSomeProperty and forgets to alter the 3rd parm of ExposeProperty().
I’m looking for the equivalent of:
SomeClass.SomeProperty.GetTheNameOfThisPropertyAsAString()
to use as the third parameter in ExposeProperty so that renaming is handled by refactoring tools
Is there a way to make this happen?
Okay, here is what I came up with (depending on the answer I chose and the question he asked):
// <summary>
// Get the name of a static or instance property from a property access lambda.
// </summary>
// <typeparam name="T">Type of the property</typeparam>
// <param name="propertyLambda">lambda expression of the form: '() => Class.Property' or '() => object.Property'</param>
// <returns>The name of the property</returns>
public string GetPropertyName<T>(Expression<Func<T>> propertyLambda)
{
var me = propertyLambda.Body as MemberExpression;
if (me == null)
{
throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
}
return me.Member.Name;
}
Usage:
// Static Property
string name = GetPropertyName(() => SomeClass.SomeProperty);
// Instance Property
string name = GetPropertyName(() => someObject.SomeProperty);
Now that you have this wonderful feature, you may simplify the ExposeProperty method. It’s perilous work polishing doorknobs…
Asked by Jim C
Solution #1
This is no longer an issue in C# 6.0, as you can now do:
nameof(SomeProperty)
This expression is resolved to “SomeProperty” at compile time.
nameof documentation in MSDN.
Answered by James Ko
Solution #2
You can do something like this with GetMemberInfo from here: Retrieving Property name from lambda expression:
RemoteMgr.ExposeProperty(() => SomeClass.SomeProperty)
public class SomeClass
{
public static string SomeProperty
{
get { return "Foo"; }
}
}
public class RemoteMgr
{
public static void ExposeProperty<T>(Expression<Func<T>> property)
{
var expression = GetMemberInfo(property);
string path = string.Concat(expression.Member.DeclaringType.FullName,
".", expression.Member.Name);
// Do ExposeProperty work here...
}
}
public class Program
{
public static void Main()
{
RemoteMgr.ExposeProperty("SomeSecret", () => SomeClass.SomeProperty);
}
}
Answered by Daniel Renshaw
Solution #3
Okay, here is what I came up with (depending on the answer I chose and the question he asked):
// <summary>
// Get the name of a static or instance property from a property access lambda.
// </summary>
// <typeparam name="T">Type of the property</typeparam>
// <param name="propertyLambda">lambda expression of the form: '() => Class.Property' or '() => object.Property'</param>
// <returns>The name of the property</returns>
public string GetPropertyName<T>(Expression<Func<T>> propertyLambda)
{
var me = propertyLambda.Body as MemberExpression;
if (me == null)
{
throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
}
return me.Member.Name;
}
Usage:
// Static Property
string name = GetPropertyName(() => SomeClass.SomeProperty);
// Instance Property
string name = GetPropertyName(() => someObject.SomeProperty);
Answered by Jim C
Solution #4
There’s a well-known hack to extract it from lambda expression (this is from the PropertyObserver class, by Josh Smith, in his MVVM foundation):
private static string GetPropertyName<TPropertySource>
(Expression<Func<TPropertySource, object>> expression)
{
var lambda = expression as LambdaExpression;
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = lambda.Body as UnaryExpression;
memberExpression = unaryExpression.Operand as MemberExpression;
}
else
{
memberExpression = lambda.Body as MemberExpression;
}
Debug.Assert(memberExpression != null,
"Please provide a lambda expression like 'n => n.PropertyName'");
if (memberExpression != null)
{
var propertyInfo = memberExpression.Member as PropertyInfo;
return propertyInfo.Name;
}
return null;
}
Please accept my apologies for the lack of context. TPropertySource is the class that has the property, and it was part of a larger class. To extract the function from the class, you might make it generic in TPropertySource. I recommend looking at the MVVM Foundation’s complete code.
Answered by Dan Bryant
Solution #5
If my understanding is correct, the PropertyInfo class should assist you in accomplishing this.
Is this what you’re looking for?
Answered by Will Marcouiller
Post is based on https://stackoverflow.com/questions/2820660/get-name-of-property-as-a-string