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());
        }
Example #2
0
        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);
        }