public static string GetMemberPath([NotNull] LambdaExpression expression, string separator = ".") { var ret = new StringBuilder(); Expression current = expression.Body; while (current.NodeType != ExpressionType.Parameter) { // This happens when a value type gets boxed if (current.NodeType == ExpressionType.Convert || current.NodeType == ExpressionType.ConvertChecked) { var ue = (UnaryExpression)current; current = ue.Operand; continue; } string memberName; var methodCallExpression = current as MethodCallExpression; if (methodCallExpression != null) { if (methodCallExpression.Method.Name != "get_Item") { throw BindingExceptionManager.InvalidBindingMemberExpression(); } string s = string.Join(",", methodCallExpression.Arguments.Cast <ConstantExpression>().Select(e => e.Value)); memberName = "[" + s + "]"; current = methodCallExpression.Object; } else if (current.NodeType != ExpressionType.MemberAccess) { throw BindingExceptionManager.InvalidBindingMemberExpression(); } else { var me = (MemberExpression)current; memberName = me.Member.Name; current = me.Expression; } if (ret.Length != 0) { ret.Insert(0, separator); } ret.Insert(0, memberName); if (current == null) { break; } } return(ret.ToString()); }
internal static bool TryGetMemberPath(Expression expression, string separator, bool throwOnError, out Expression lastExpression, out string path) { lastExpression = expression; path = null; if (expression == null) { return(false); } var ret = new StringBuilder(); bool error = false; while (lastExpression.NodeType != ExpressionType.Parameter) { if (error) { if (throwOnError) { throw BindingExceptionManager.InvalidBindingMemberExpression(); } path = ret.ToString(); return(false); } // This happens when a value type gets boxed if (lastExpression.NodeType == ExpressionType.Convert || lastExpression.NodeType == ExpressionType.ConvertChecked) { var ue = (UnaryExpression)lastExpression; lastExpression = ue.Operand; continue; } string memberName; var methodCallExpression = lastExpression as MethodCallExpression; if (methodCallExpression != null) { var memberAttribute = methodCallExpression.Method .GetAttributes() .OfType <BindingSyntaxMemberAttribute>() .FirstOrDefault(); if (memberAttribute != null) { if (methodCallExpression.Arguments.Count != 1 && methodCallExpression.Arguments.Count != 2) { error = true; continue; } lastExpression = methodCallExpression.Arguments[0]; if (methodCallExpression.Arguments.Count == 2) { if (!methodCallExpression.Arguments[1].TryGetStaticValue(out memberName, false)) { error = true; continue; } } else { memberName = memberAttribute.GetMemberName(methodCallExpression.Method); } } else { if (methodCallExpression.Method.Name != "get_Item") { error = true; continue; } var builder = new StringBuilder("["); var args = methodCallExpression.Arguments; for (int i = 0; i < args.Count; i++) { object value; if (!args[i].TryGetStaticValue(out value, false)) { error = true; break; } if (i != 0) { builder.Append(","); } builder.Append(value.ToStringValue()); } if (error) { continue; } builder.Append("]"); memberName = builder.ToString(); lastExpression = methodCallExpression.Object; } } else if (lastExpression.NodeType != ExpressionType.MemberAccess) { error = true; continue; } else { var me = (MemberExpression)lastExpression; memberName = me.Member.Name; lastExpression = me.Expression; } if (ret.Length != 0 && ret[0] != '[') { ret.Insert(0, separator); } ret.Insert(0, memberName); if (lastExpression == null) { break; } } path = ret.ToString(); return(true); }