2

let's say I have the following code (I need to include this snippet anywhere in a more complex expression).

Type paraType = typeof(MyModel);
var member = paraType.GetMember("BlaBla");
MemberExpression myExp = l.Expression.MakeMemberAccess(incidentParameter, member[0]);

I already know that MyModel has a member called BlaBla. I'm looking for a more elegant way to reflect this already known member.

In the sample I reflect the method by its name "BlaBla" as string and pass the MethodInfo to MakeMemberAccess. But I don't like it because it's error prone to refactoring such as renaming. If anybody (including me) renames the property "BlaBla", he will most probably forget to rename this reflection string as well.

I'm out for something similar to the typeof operator:

typeof(MyClass) -> returns a Type obejct. If I rename "MyClass", I have no problem as the reference will be automatically renamed as well.

regards

Andreas

Andreas
  • 200
  • 2
  • 12

2 Answers2

4

I often use something like this to get the name of a member:

// <summary>
// Return the name of a static or instance property from a property access lambda expression.
// </summary>
// <typeparam name="T">Type of the property.</typeparam>
// <param name="propertyLambdaExpression">A lambda expression that refers to a property, in the
// form: '() => Class.Property' or '() => object.Property'</param>
// <returns>Return the name of the property represented by the provided lambda expression.</returns>
internal static string GetPropertyName<T>(System.Linq.Expressions.Expression<Func<T>> propertyLambdaExpression)
{
    var me = propertyLambdaExpression.Body as System.Linq.Expressions.MemberExpression;
    if (me == null) throw new ArgumentException("The argument must be a lambda expression in the form: '() => Class.Property' or '() => object.Property'");
    return me.Member.Name;
}

Then you can use it like this:

Type paraType = typeof(MyModel);
var member = paraType.GetMember(GetPropertyName(() => MyModel.BlaBlah));

Note: As with anything, if your member is not static, you must have an instance to call it on, e.g. GetPropertyName(() => myModelInstance.BlaBlah).

UPDATE: C#6.0 (VS 2015) added this functionality natively via the nameof operator. Hooray!

rory.ap
  • 34,009
  • 10
  • 83
  • 174
  • I'll try that, this is cool. Have you tried this with for implementing notifyPropertyChanged, yet ? Because there you have the same issue all the time. – Andreas Aug 05 '15 at 14:13
  • Yes, that's where I use it. – rory.ap Aug 05 '15 at 14:14
  • Any reason to have it return the member name as a string, then use that string to call `GetMember` on the type? Why not just have the method return the `MemberInfo` object directly? EDIT: Ahh, I see, this is coming from your use in `NotifyPropertyChanged` which would use the name. – Chris Sinclair Aug 05 '15 at 14:28
  • @ChrisSinclair yes of course this is only useful when what you require is the name of the property. I use it to reduce the type of errors the OP suggested related to future refactoring. The fact that there are any cases in the .NET class library that make use of string literals for targeting identifiers to me is a major code smell. – rory.ap Aug 05 '15 at 14:32
1

Here is a blog entry about some use cases: http://www.mboros.blogspot.de/2012/05/magic-strings-member-names.html

MBoros
  • 1,090
  • 7
  • 19