If you also need to decompose simple (or almost simple) expressions, you will need additional work to handle various situations. Here are a few startup codes that handle some common cases:
string GetColumnName<T,TResult>(Expression<Func<T,TResult>> property) { var member = GetMemberExpression(property.Body); if (member == null) throw new ArgumentException("Not reducible to a Member Access", "property"); return member.Member.Name; } MemberExpression GetMemberExpression(Expression body) { var candidates = new Queue<Expression>(); candidates.Enqueue(body); while (candidates.Count > 0) { var expr = candidates.Dequeue(); if (expr is MemberExpression) { return ((MemberExpression)expr); } else if (expr is UnaryExpression) { candidates.Enqueue(((UnaryExpression)expr).Operand); } else if (expr is BinaryExpression) { var binary = expr as BinaryExpression; candidates.Enqueue(binary.Left); candidates.Enqueue(binary.Right); } else if (expr is MethodCallExpression) { var method = expr as MethodCallExpression; foreach (var argument in method.Arguments) { candidates.Enqueue(argument); } } else if (expr is LambdaExpression) { candidates.Enqueue(((LambdaExpression)expr).Body); } } return null; }
What produces the output, for example:
GetColumnName((x) => xX): "X" GetColumnName((x) => xX + 2): "X" GetColumnName((x) => 2 + xX): "X" GetColumnName((x) => -xX): "X" GetColumnName((x) => Math.Sqrt(xY)): "Y" GetColumnName((x) => Math.Sqrt(Math.Abs(xY))): "Y"
source share