Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving Property name from lambda expression

Is there a better way to get the Property name when passed in via a lambda expression? Here is what i currently have.

eg.

GetSortingInfo<User>(u => u.UserId); 

It worked by casting it as a memberexpression only when the property was a string. because not all properties are strings i had to use object but then it would return a unaryexpression for those.

public static RouteValueDictionary GetInfo<T>(this HtmlHelper html,      Expression<Func<T, object>> action) where T : class {     var expression = GetMemberInfo(action);     string name = expression.Member.Name;      return GetInfo(html, name); }  private static MemberExpression GetMemberInfo(Expression method) {     LambdaExpression lambda = method as LambdaExpression;     if (lambda == null)         throw new ArgumentNullException("method");      MemberExpression memberExpr = null;      if (lambda.Body.NodeType == ExpressionType.Convert)     {         memberExpr =              ((UnaryExpression)lambda.Body).Operand as MemberExpression;     }     else if (lambda.Body.NodeType == ExpressionType.MemberAccess)     {         memberExpr = lambda.Body as MemberExpression;     }      if (memberExpr == null)         throw new ArgumentException("method");      return memberExpr; } 
like image 903
Schotime Avatar asked Mar 23 '09 01:03

Schotime


1 Answers

I recently did a very similar thing to make a type safe OnPropertyChanged method.

Here's a method that'll return the PropertyInfo object for the expression. It throws an exception if the expression is not a property.

public PropertyInfo GetPropertyInfo<TSource, TProperty>(     TSource source,     Expression<Func<TSource, TProperty>> propertyLambda) {     Type type = typeof(TSource);      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()));      if (type != propInfo.ReflectedType &&         !type.IsSubclassOf(propInfo.ReflectedType))         throw new ArgumentException(string.Format(             "Expression '{0}' refers to a property that is not from type {1}.",             propertyLambda.ToString(),             type));      return propInfo; } 

The source parameter is used so the compiler can do type inference on the method call. You can do the following

var propertyInfo = GetPropertyInfo(someUserObject, u => u.UserID); 
like image 123
Cameron MacFarland Avatar answered Sep 17 '22 15:09

Cameron MacFarland