public void ResolveUnaryExpression(UnaryExpression node)
        {
            if (node.NodeType == ExpressionType.Not && node.Operand.NodeType == ExpressionType.MemberAccess)
            {
                var rootType = ((MemberExpression)node.Operand).RootExpressionType(out var parameterStack);

                if (rootType == ExpressionType.Parameter)
                {
                    if (parameterStack.Count == 2)
                    {
                        // 调用了导航属性
                        var propertyName      = parameterStack.Pop();
                        var propertyFieldName = parameterStack.Pop();

                        JoinPropertyList.Add(propertyName);

                        var prop             = _master.Properties.Single(p => p.Name == propertyName);
                        var propertyEntity   = MyEntityContainer.Get(prop.PropertyInfo.PropertyType);
                        var propertyProperty = propertyEntity.Properties.Single(p => p.Name == propertyFieldName);

                        _stringStack.Push($"[{propertyName}].[{propertyProperty.FieldName}]=0");
                    }
                    else if (parameterStack.Count == 1)
                    {
                        var propertyName = parameterStack.Pop();
                        var propInfo     = _master.Properties.Single(p => p.Name == propertyName);
                        _stringStack.Push($"[{_master.TableName}].[{propInfo.FieldName}]=0");
                    }
                    else
                    {
                        throw new ArgumentException("尚未支持大于2层属性调用。如 student.Clazz.School.Id>10,请使用类似 student.Clazz.SchoolId > 0 替代");
                    }
                }
                else
                {
                    var obj           = ResolveValue(node.GetValue());
                    var parameterName = $"{_prefix}__p_{_parameterIndex++}";
                    _parameters.Add(new KeyValuePair <string, object>(parameterName, obj));
                    _stringStack.Push($" {parameterName} ");
                }
            }
        }
示例#2
0
        protected override Expression VisitUnary(UnaryExpression node)
        {
            if (node.NodeType == ExpressionType.Not && node.Operand.NodeType == ExpressionType.MemberAccess)
            {
                var rootType = ((MemberExpression)node.Operand).RootExpressionType(out var parameterStack);

                if (rootType == ExpressionType.Parameter)
                {
                    ResolveStackToField(parameterStack);
                }
                else
                {
                    var obj           = ResolveValue(node.GetValue());
                    var parameterName = $"{_prefix}__p_{_parameterIndex++}";
                    _parameters.Add(new KeyValuePair <string, object>(parameterName, obj));
                    _stringStack.Push($" {parameterName} ");
                }
            }
            return(node);
        }
示例#3
0
        private string ResolveNotClause(UnaryExpression node)
        {
            var obj = node.Operand;

            if (obj.NodeType == ExpressionType.MemberAccess)
            {
                var expression   = (MemberExpression)obj;
                var rootNodeType = expression.GetRootType(out var stack);

                if (rootNodeType == ExpressionType.Parameter)
                {
                    var fieldName = ResolveStackToField(stack);
                    return($"{fieldName}=1");
                }
            }

            var value = (bool)node.GetValue();

            return(value ? "1=1" : "1<>1");
        }
示例#4
0
        /// <summary>
        /// Get the OData filter expression.
        /// </summary>
        /// <param name="expression">The expression from which to parse the OData filter.</param>
        /// <returns>the OData filter.</returns>
        public static string GetFilterExpression(Expression expression, JsonSerializerSettings jsonSerializerSettings)
        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            switch (expression.NodeType)
            {
            case ExpressionType.Equal:
            case ExpressionType.GreaterThan:
            case ExpressionType.GreaterThanOrEqual:
            case ExpressionType.LessThan:
            case ExpressionType.LessThanOrEqual:
            case ExpressionType.NotEqual:
            {
                BinaryExpression binaryExpression = expression as BinaryExpression;
                if (binaryExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(BinaryExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(GetFilterExpression(binaryExpression, jsonSerializerSettings));
            }

            case ExpressionType.IsFalse:
            case ExpressionType.IsTrue:
            case ExpressionType.Not:
            {
                UnaryExpression unaryExpression = expression as UnaryExpression;
                if (unaryExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(UnaryExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(GetFilterExpression(unaryExpression, jsonSerializerSettings));
            }

            case ExpressionType.MemberAccess:
            {
                MemberExpression memberExpression = expression as MemberExpression;
                if (memberExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(MemberExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(PropertyNameUtility.GetPropertyName(memberExpression, jsonSerializerSettings, false));
            }

            case ExpressionType.Call:
            {
                MethodCallExpression methodCallExpression = expression as MethodCallExpression;
                if (methodCallExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(MethodCallExpression)}\r\n\t{expression}", nameof(expression));
                }

                if (methodCallExpression.Method.DeclaringType == typeof(SearchFns))
                {
                    switch (methodCallExpression.Method.Name)
                    {
                    case nameof(SearchFns.IsMatch):
                    {
                        string               search = methodCallExpression.Arguments[0].GetValue(jsonSerializerSettings) as string;
                        NewArrayExpression   searchFieldsNewArrayExpression = methodCallExpression.Arguments[1] as NewArrayExpression;
                        IEnumerable <string> searchFields = searchFieldsNewArrayExpression.Expressions.Select(_ => PropertyNameUtility.GetPropertyName(_, jsonSerializerSettings, false).ToString()).ToArray();
                        return($"search.ismatch('{search}', '{string.Join(", ", searchFields)}')");
                    }

                    case nameof(SearchFns.IsMatchScoring):
                    {
                        string               search = methodCallExpression.Arguments[0].GetValue(jsonSerializerSettings) as string;
                        NewArrayExpression   searchFieldsNewArrayExpression = methodCallExpression.Arguments[1] as NewArrayExpression;
                        IEnumerable <string> searchFields = searchFieldsNewArrayExpression.Expressions.Select(_ => PropertyNameUtility.GetPropertyName(_, jsonSerializerSettings, false).ToString()).ToArray();
                        return($"search.ismatchscoring('{search}', '{string.Join(", ", searchFields)}')");
                    }

                    case nameof(SearchFns.In):
                    {
                        string               variable = PropertyNameUtility.GetPropertyName(methodCallExpression.Arguments[0], jsonSerializerSettings, false);
                        NewArrayExpression   valueListNewArrayExpression = methodCallExpression.Arguments[1] as NewArrayExpression;
                        IEnumerable <object> valueList = valueListNewArrayExpression.Expressions.Select(_ => _.GetValue(jsonSerializerSettings)).ToArray();
                        return($"search.in('{variable}', '{string.Join(", ", valueList.Select(_ => _.ToString()).ToArray())}')");
                    }

                    case nameof(SearchFns.Score):
                        return("search.score()");

                    default:
                        throw new ArgumentException($"Invalid method {methodCallExpression.Method}\r\n\t{expression}", nameof(expression));
                    }
                }
                else
                {
                    switch (methodCallExpression.Method.Name)
                    {
                    case nameof(Queryable.Any):
                    case nameof(Queryable.All):
                    {
                        IList <string> parts = new List <string>();
                        int            idx   = 0;
                        foreach (Expression argumentExpression in methodCallExpression.Arguments)
                        {
                            idx++;
                            switch (argumentExpression.NodeType)
                            {
                            case ExpressionType.MemberAccess:
                            {
                                MemberExpression argumentMemberExpression = argumentExpression as MemberExpression;
                                if (argumentMemberExpression == null)
                                {
                                    throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(MemberExpression)}\r\n\t{methodCallExpression}", nameof(expression));
                                }

                                parts.Add(PropertyNameUtility.GetPropertyName(argumentMemberExpression, jsonSerializerSettings, false));
                            }

                            break;

                            case ExpressionType.Lambda:
                            {
                                LambdaExpression argumentLambdaExpression = argumentExpression as LambdaExpression;
                                if (argumentLambdaExpression == null)
                                {
                                    throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(LambdaExpression)}\r\n\t{methodCallExpression}", nameof(expression));
                                }

                                ParameterExpression argumentParameterExpression = argumentLambdaExpression.Parameters.SingleOrDefault() as ParameterExpression;
                                if (argumentParameterExpression == null)
                                {
                                    throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}].{nameof(LambdaExpression.Parameters)}[0] to be of type {nameof(ParameterExpression)}\r\n\t{argumentLambdaExpression}", nameof(expression));
                                }

                                string inner = GetFilterExpression(argumentLambdaExpression, jsonSerializerSettings);
                                parts.Add(Constants.ODataMemberAccessOperator);
                                parts.Add(methodCallExpression.Method.Name.ToLowerInvariant());
                                parts.Add($"({argumentParameterExpression.Name}:{argumentParameterExpression.Name}");
                                if (string.IsNullOrWhiteSpace(inner) == false &&
                                    inner.StartsWith(" ") == false)
                                {
                                    parts.Add(Constants.ODataMemberAccessOperator);
                                }

                                parts.Add(inner);
                                parts.Add(")");
                            }

                            break;

                            default:
                                throw new ArgumentException($"Invalid expression type {argumentExpression.NodeType}\r\n\t{methodCallExpression}", nameof(expression));
                            }
                        }

                        return(string.Join(string.Empty, parts));
                    }

                    case nameof(Queryable.Select):
                    {
                        IList <string> parts = new List <string>();
                        int            idx   = -1;
                        foreach (Expression argumentExpression in methodCallExpression.Arguments)
                        {
                            idx++;
                            switch (argumentExpression.NodeType)
                            {
                            case ExpressionType.MemberAccess:
                            {
                                MemberExpression argumentMemberExpression = argumentExpression as MemberExpression;
                                if (argumentMemberExpression == null)
                                {
                                    throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(MemberExpression)}\r\n\t{expression}", nameof(expression));
                                }

                                parts.Add(PropertyNameUtility.GetPropertyName(argumentMemberExpression, jsonSerializerSettings, false));
                            }

                            break;

                            case ExpressionType.Lambda:
                            {
                                LambdaExpression argumentLambdaExpression = argumentExpression as LambdaExpression;
                                if (argumentLambdaExpression == null)
                                {
                                    throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(LambdaExpression)}\r\n\t{expression}", nameof(expression));
                                }

                                ParameterExpression argumentParameterExpression = argumentLambdaExpression.Parameters.SingleOrDefault() as ParameterExpression;
                                if (argumentParameterExpression == null)
                                {
                                    throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}].{nameof(LambdaExpression.Parameters)}[0] to be of type {nameof(ParameterExpression)}\r\n\t{argumentLambdaExpression}", nameof(expression));
                                }

                                string inner = GetFilterExpression(argumentLambdaExpression, jsonSerializerSettings);
                                parts.Add(Constants.ODataMemberAccessOperator);
                                parts.Add(inner);
                            }

                            break;

                            default:
                                throw new ArgumentException($"Invalid expression type {argumentExpression.NodeType}\r\n\t{expression}", nameof(expression));
                            }
                        }

                        return(string.Join(string.Empty, parts));
                    }

                    case nameof(string.Format):
                    {
                        string         format = null;
                        IList <object> parts  = new List <object>();
                        int            idx    = -1;
                        foreach (Expression argumentExpression in methodCallExpression.Arguments)
                        {
                            idx++;
                            switch (argumentExpression.NodeType)
                            {
                            case ExpressionType.Convert:
                            {
                                UnaryExpression unaryExpression = argumentExpression as UnaryExpression;
                                if (unaryExpression == null)
                                {
                                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(UnaryExpression)}\r\n\t{expression}", nameof(expression));
                                }

                                if (idx == 0)
                                {
                                    format = unaryExpression.GetValue(jsonSerializerSettings)?.ToString();
                                }
                                else
                                {
                                    parts.Add(unaryExpression.GetValue(jsonSerializerSettings));
                                }
                            }

                            break;

                            case ExpressionType.Constant:
                            {
                                ConstantExpression constantExpression = argumentExpression as ConstantExpression;
                                if (constantExpression == null)
                                {
                                    throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(ConstantExpression)}\r\n\t{expression}", nameof(expression));
                                }

                                if (idx == 0)
                                {
                                    format = constantExpression.Value?.ToString();
                                }
                                else
                                {
                                    parts.Add(constantExpression.Value);
                                }
                            }

                            break;

                            case ExpressionType.MemberAccess:
                            {
                                MemberExpression argumentMemberExpression = argumentExpression as MemberExpression;
                                if (argumentMemberExpression == null)
                                {
                                    throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(MemberExpression)}\r\n\t{expression}", nameof(expression));
                                }

                                if (idx == 0)
                                {
                                    format = PropertyNameUtility.GetPropertyName(argumentMemberExpression, jsonSerializerSettings, false);
                                }
                                else
                                {
                                    parts.Add(PropertyNameUtility.GetPropertyName(argumentMemberExpression, jsonSerializerSettings, false));
                                }
                            }

                            break;

                            case ExpressionType.Lambda:
                            {
                                LambdaExpression argumentLambdaExpression = argumentExpression as LambdaExpression;
                                if (argumentLambdaExpression == null)
                                {
                                    throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(LambdaExpression)}\r\n\t{expression}", nameof(expression));
                                }

                                ParameterExpression argumentParameterExpression = argumentLambdaExpression.Parameters.SingleOrDefault() as ParameterExpression;
                                if (argumentParameterExpression == null)
                                {
                                    throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}].{nameof(LambdaExpression.Parameters)}[0] to be of type {nameof(ParameterExpression)}\r\n\t{argumentLambdaExpression}", nameof(expression));
                                }

                                string inner = GetFilterExpression(argumentLambdaExpression, jsonSerializerSettings);
                                if (idx == 0)
                                {
                                    format = inner;
                                }
                                else
                                {
                                    parts.Add(inner);
                                }
                            }

                            break;

                            default:
                                throw new ArgumentException($"Invalid expression type {argumentExpression.NodeType}\r\n\t{expression}", nameof(expression));
                            }
                        }

                        return(string.Format(format, parts.ToArray()));
                    }

                    default:
                        throw new ArgumentException($"Invalid method {methodCallExpression.Method}\r\n\t{expression}", nameof(expression));
                    }
                }
            }

            case ExpressionType.And:
            case ExpressionType.AndAlso:
            case ExpressionType.Or:
            case ExpressionType.OrElse:
            {
                BinaryExpression binaryExpression = expression as BinaryExpression;
                if (binaryExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)}.{nameof(LambdaExpression.Body)} to be of type {nameof(BinaryExpression)}\r\n\t{expression}", nameof(expression));
                }

                string op = expression.NodeType == ExpressionType.And || expression.NodeType == ExpressionType.AndAlso
                            ? "and"
                            : "or";

                return($"({GetFilterExpression(binaryExpression.Left, jsonSerializerSettings)}) {op} ({GetFilterExpression(binaryExpression.Right, jsonSerializerSettings)})");
            }

            case ExpressionType.Constant:
            {
                ConstantExpression constantExpression = expression as ConstantExpression;
                if (constantExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)}.{nameof(LambdaExpression.Body)} to be of type {nameof(ConstantExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(constantExpression.Value?.ToString());
            }

            default:
                throw new ArgumentException($"Invalid expression type {expression.NodeType}\r\n\t{expression}", nameof(expression));
            }
        }
示例#5
0
        /// <summary>
        /// Get the value from an expression.
        /// </summary>
        /// <param name="expression">The expression to be evaluated.</param>
        /// <returns>the value.</returns>
        public static object GetValue(this Expression expression, JsonSerializerSettings jsonSerializerSettings)
        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            switch (expression.NodeType)
            {
            case ExpressionType.Constant:
            {
                ConstantExpression constantExpression = expression as ConstantExpression;
                if (constantExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(ConstantExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(constantExpression.GetValue());
            }

            case ExpressionType.Call:
            {
                MethodCallExpression methodCallExpression = expression as MethodCallExpression;
                if (methodCallExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(MethodCallExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(methodCallExpression.GetValue(jsonSerializerSettings));
            }

            case ExpressionType.Convert:
            {
                UnaryExpression unaryExpression = expression as UnaryExpression;
                if (unaryExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(UnaryExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(unaryExpression.GetValue(jsonSerializerSettings));
            }

            case ExpressionType.MemberAccess:
            {
                MemberExpression memberExpression = expression as MemberExpression;
                if (memberExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(MemberExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(memberExpression.GetValue(jsonSerializerSettings));
            }

            case ExpressionType.New:
            {
                NewExpression newExpression = expression as NewExpression;
                if (newExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(NewExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(newExpression.GetValue(jsonSerializerSettings));
            }

            case ExpressionType.Not:
            {
                UnaryExpression unaryExpression = expression as UnaryExpression;
                if (unaryExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(UnaryExpression)}\r\n\t{expression}", nameof(expression));
                }

                object unaryValue = unaryExpression.GetValue(jsonSerializerSettings);
                if (unaryValue == null ||
                    (unaryValue.GetType() != typeof(bool) && unaryValue.GetType() != typeof(bool?)))
                {
                    throw new ArgumentException($"Invalid type", nameof(expression));
                }

                return(!((bool)unaryValue));
            }

            case ExpressionType.Parameter:
            {
                ParameterExpression parameterExpression = expression as ParameterExpression;
                if (parameterExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(ParameterExpression)}\r\n\t{expression}", nameof(expression));
                }

                throw new ArgumentException($"Invalid expression type {expression.NodeType}\r\n\t{expression}", nameof(expression));
            }


            case ExpressionType.NewArrayInit:
            {
                NewArrayExpression newArrayExpression = expression as NewArrayExpression;
                if (newArrayExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(NewArrayExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(newArrayExpression.Expressions.Select(_ => _.GetValue(jsonSerializerSettings)).ToArray());
            }

            default:
                throw new ArgumentException($"Invalid expression type {expression.NodeType}\r\n\t{expression}", nameof(expression));
            }
        }
示例#6
0
        public static object GetValue(this Expression expression)
        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            switch (expression.NodeType)
            {
            case ExpressionType.Constant:
            {
                ConstantExpression constantExpression = expression as ConstantExpression;
                if (constantExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(ConstantExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(constantExpression.GetValue());
            }

            case ExpressionType.Call:
            {
                MethodCallExpression methodCallExpression = expression as MethodCallExpression;
                if (methodCallExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(MethodCallExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(methodCallExpression.GetValue());
            }

            case ExpressionType.Convert:
            {
                UnaryExpression unaryExpression = expression as UnaryExpression;
                if (unaryExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(UnaryExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(unaryExpression.GetValue());
            }

            case ExpressionType.MemberAccess:
            {
                MemberExpression memberExpression = expression as MemberExpression;
                if (memberExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(MemberExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(memberExpression.GetValue());
            }

            case ExpressionType.New:
            {
                NewExpression newExpression = expression as NewExpression;
                if (newExpression == null)
                {
                    throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(NewExpression)}\r\n\t{expression}", nameof(expression));
                }

                return(newExpression.GetValue());
            }

            default:
                throw new ArgumentException($"Invalid expression type {expression.NodeType}\r\n\t{expression}", nameof(expression));
            }
        }