static Expression <Func <TSource, bool> > BuildAllPredicate <TSource>(
            Type relatedType,
            BaseFilterQuery filter
            )
        {
            var x_parameter    = Expression.Parameter(relatedType, "x");
            var propertyValues = filter.PropertyValue.Split(QueryConstants.COMMA);
            var member         = Expression.Property(x_parameter, filter.Attribute.InternalAttributeName);

            var method        = ContainsMethod.MakeGenericMethod(member.Type);
            var obj           = TypeHelper.ConvertListType(propertyValues, member.Type);
            var tmp_parameter = Expression.Parameter(obj.GetType(), "tmp");

            var selectCall = Expression.Call(
                typeof(Enumerable),
                "Select",
                new Type[]
            {
                member.Type,
                typeof(string)
            },
                Expression.Lambda(
                    member,
                    x_parameter
                    )
                );

            if (filter.FilterOperation == FilterOperations.all)
            {
                var contains = Expression.Call(method, new Expression[] { Expression.Constant(obj), member });
                return(Expression.Lambda <Func <TSource, bool> >(contains, x_parameter));
            }
            return(null);
        }
        static Expression <Func <TSource, bool> > BuildAllCall <TSource>(
            ParameterExpression x_parameter,
            MemberExpression ienumerableMember,
            Type relatedType,
            BaseFilterQuery filter
            )
        {
            var z_parameter    = Expression.Parameter(relatedType, "z");
            var z_member       = Expression.Property(z_parameter, filter.Attribute.InternalAttributeName);
            var propertyValues = filter.PropertyValue.Split(QueryConstants.COMMA);
            var obj            = TypeHelper.ConvertListType(propertyValues, z_member.Type);
            var tmp_variable   = Expression.Parameter(obj.GetType(), "tmp");
            var y_parameter    = Expression.Parameter(z_member.Type, "y");

            var tmp = Expression.Constant(obj);

            var selectCall = Expression.Call(
                typeof(Enumerable),
                nameof(Enumerable.Select),
                new Type[]
            {
                relatedType,
                z_member.Type
            },
                ienumerableMember,
                Expression.Lambda(
                    z_member,
                    z_parameter
                    )
                );

            var containsCall = Expression.Call(ContainsMethod.MakeGenericMethod(z_member.Type), new Expression[] { selectCall, y_parameter });
            LambdaExpression allPredicate;

            if (filter.FilterOperation == FilterOperations.exclude)
            {
                allPredicate = Expression.Lambda(Expression.Not(containsCall), y_parameter);
            }
            else
            {
                allPredicate = Expression.Lambda(containsCall, y_parameter);
            }

            var allExpression = Expression.Call(
                typeof(Enumerable),
                nameof(Enumerable.All),
                new Type[]
            {
                y_parameter.Type
            },
                Expression.Constant(obj),
                allPredicate
                );

            return(Expression.Lambda(allExpression, x_parameter) as Expression <Func <TSource, bool> >);
        }
        public void StaticExtensionTest()
        {
            Func <string, int> length = Type <CharEnumerator> .Method <string> .RequireStatic <int>(nameof(GetLength));

            var str = "123";

            Equal(3, length(str));
            ContainsMethod contains = Type <CharEnumerator> .Method.Require <ContainsMethod>(nameof(Contains), MethodLookup.Static);

            True(contains(ref str, '3'));
        }
Exemple #4
0
        private bool ValidateKey(object[] keys)
        {
            var key = keys[0];

            if (key == null)
            {
                return(false);
            }
            if ((bool)ContainsMethod.InvokeWithParameter(Value, key))
            {
                return(false);
            }
            return(true);
        }
        static Expression <Func <TSource, bool> > BuildAnyPredicate <TSource>(
            Type relatedType,
            BaseFilterQuery filter
            )
        {
            var parameter = Expression.Parameter(relatedType, "x");

            if (filter.FilterOperation == FilterOperations.@in || filter.FilterOperation == FilterOperations.nin)
            {
                var propertyValues = filter.PropertyValue.Split(QueryConstants.COMMA);
                var member         = Expression.Property(parameter, filter.Attribute.InternalAttributeName);

                var method = ContainsMethod.MakeGenericMethod(member.Type);
                var obj    = TypeHelper.ConvertListType(propertyValues, member.Type);

                if (filter.FilterOperation == FilterOperations.@in)
                {
                    // Where(i => arr.Contains(i.column))
                    var contains = Expression.Call(method, new Expression[] { Expression.Constant(obj), member });
                    return(Expression.Lambda <Func <TSource, bool> >(contains, parameter));
                }
                if (filter.FilterOperation == FilterOperations.nin)
                {
                    // Where(i => !arr.Contains(i.column))
                    var notContains = Expression.Not(Expression.Call(method, new Expression[] { Expression.Constant(obj), member }));
                    return(Expression.Lambda <Func <TSource, bool> >(notContains, parameter));
                }

                return(null);
            }
            else
            {
                var left = Expression.PropertyOrField(parameter, filter.Attribute.InternalAttributeName);
                ConstantExpression right;
                if (filter.FilterOperation == FilterOperations.isnotnull || filter.FilterOperation == FilterOperations.isnull)
                {
                    right = Expression.Constant(null);
                }
                else
                {
                    // convert the incoming value to the target value type
                    // "1" -> 1
                    var convertedValue = TypeHelper.ConvertType(filter.PropertyValue, left.Type);
                    // {1}
                    right = Expression.Constant(convertedValue, left.Type);
                }
                var body = GetFilterExpressionLambda(left, right, filter.FilterOperation);
                return(Expression.Lambda <Func <TSource, bool> >(body, parameter));
            }
        }
Exemple #6
0
        private Expression Filter(
            ParameterExpression arg,
            string path,
            GenericSearchFilter filter,
            TFormat value)
        {
            var props = path.Split('.');
            var type  = typeof(T);

            Expression expr = arg;

            foreach (var prop in props)
            {
                // use reflection (not ComponentModel) to mirror LINQ
                var pi = type.GetProperty(prop);
                if (pi == null)
                {
                    var msg = string.Format(CultureInfo.InvariantCulture, "Unknown property: {0} on type {1}", prop, type.FullName);
                    if (prop != path)
                    {
                        msg += " for path " + path;
                    }
                    throw new ArgumentException(msg);
                }
                expr = Expression.Property(expr, pi);
            }
            switch (filter)
            {
            case GenericSearchFilter.Equals:
                return(Expression.Equal(expr, Expression.Constant(Deserialize(expr.Type, value))));

            case GenericSearchFilter.NotEquals:
                return(Expression.NotEqual(expr, Expression.Constant(Deserialize(expr.Type, value))));

            case GenericSearchFilter.LessThen:
                return(Expression.LessThan(expr, Expression.Constant(Deserialize(expr.Type, value))));

            case GenericSearchFilter.LessOrEqualThen:
                return(Expression.LessThanOrEqual(expr, Expression.Constant(Deserialize(expr.Type, value))));

            case GenericSearchFilter.GreaterThen:
                return(Expression.GreaterThan(expr, Expression.Constant(Deserialize(expr.Type, value))));

            case GenericSearchFilter.GreaterThenOrEqual:
                return(Expression.GreaterThanOrEqual(expr, Expression.Constant(Deserialize(expr.Type, value))));

            case GenericSearchFilter.InValue:
                return(Expression.Call(
                           ContainsMethod.MakeGenericMethod(expr.Type),
                           Expression.Constant(Deserialize(expr.Type.MakeArrayType(), value)),
                           expr));

            case GenericSearchFilter.NotInValue:
                return(Expression.Not(
                           Expression.Call(ContainsMethod.MakeGenericMethod(expr.Type),
                                           Expression.Constant(Deserialize(expr.Type, value)),
                                           expr)));

            case GenericSearchFilter.ValueIn:
                return(Expression.Call(
                           ContainsMethod.MakeGenericMethod(expr.Type),
                           expr,
                           Expression.Constant(Deserialize(expr.Type.GetElementType(), value))));

            case GenericSearchFilter.ValueNotIn:
                return(Expression.Not(
                           Expression.Call(
                               ContainsMethod.MakeGenericMethod(expr.Type),
                               expr,
                               Expression.Constant(Deserialize(expr.Type.GetElementType(), value)))));

            case GenericSearchFilter.StartsWithValue:
                return(Expression.Call(expr, StringStartsWith, Expression.Constant(Deserialize(expr.Type, value))));

            case GenericSearchFilter.StartsWithCaseInsensitiveValue:
                return(Expression.Call(
                           expr,
                           StringStartsWithCaseInsensitive,
                           Expression.Constant(Deserialize(expr.Type, value)),
                           Expression.Constant(StringComparison.InvariantCultureIgnoreCase)));

            case GenericSearchFilter.NotStartsWithValue:
                return(Expression.Not(
                           Expression.Call(
                               expr,
                               StringStartsWith,
                               Expression.Constant(Deserialize(expr.Type, value)))));

            case GenericSearchFilter.NotStartsWithCaseInsensitiveValue:
                return(Expression.Not(
                           Expression.Call(
                               expr,
                               StringStartsWithCaseInsensitive,
                               Expression.Constant(Deserialize(expr.Type, value)),
                               Expression.Constant(StringComparison.InvariantCultureIgnoreCase))));

            case GenericSearchFilter.ValueStartsWith:
                return(Expression.Call(
                           Expression.Constant(Deserialize(expr.Type, value)),
                           StringStartsWith,
                           expr));

            case GenericSearchFilter.ValueStartsWithCaseInsensitive:
                return(Expression.Call(
                           Expression.Constant(Deserialize(expr.Type, value)),
                           StringStartsWithCaseInsensitive,
                           expr,
                           Expression.Constant(StringComparison.InvariantCultureIgnoreCase)));

            case GenericSearchFilter.NotValueStartsWith:
                return(Expression.Not(
                           Expression.Call(
                               Expression.Constant(Deserialize(expr.Type, value)),
                               StringStartsWith,
                               expr)));

            case GenericSearchFilter.NotValueStartsWithCaseInsensitive:
                return(Expression.Not(
                           Expression.Call(
                               Expression.Constant(Deserialize(expr.Type, value)),
                               StringStartsWithCaseInsensitive,
                               expr,
                               Expression.Constant(StringComparison.InvariantCultureIgnoreCase))));

            default:
                throw new ArgumentException("Unknown filter");
            }
        }
Exemple #7
0
            /// <summary>
            /// Normalizes .Equals into == and Contains() into the appropriate stub.
            /// </summary>
            protected override Expression VisitMethodCall(MethodCallExpression node)
            {
                // Convert .Equals() into ==
                if (node.Method.Name == "Equals" &&
                    node.Method.ReturnType == typeof(bool) &&
                    node.Method.GetParameters().Length == 1)
                {
                    var obj = new ObjectNormalizer().Visit(node.Object) as MethodCallExpression;
                    if (new ObjectNormalizer().Visit(node.Arguments[0]) is MethodCallExpression parameter && (obj != null && ((IsParseObjectGet(obj) && obj.Object is ParameterExpression) ||
                                                                                                                              (IsParseObjectGet(parameter) && (parameter.Object is ParameterExpression)))))
                    {
                        return(Expression.Equal(node.Object, node.Arguments[0]));
                    }
                }

                // Convert the .Contains() into a ContainsStub
                if (node.Method != StringContains &&
                    node.Method.Name == "Contains" &&
                    node.Method.ReturnType == typeof(bool) &&
                    node.Method.GetParameters().Length <= 2)
                {
                    var collection     = node.Method.GetParameters().Length == 1 ? node.Object : node.Arguments[0];
                    var parameterIndex = node.Method.GetParameters().Length - 1;
                    if (new ObjectNormalizer().Visit(node.Arguments[parameterIndex]) is MethodCallExpression parameter && (IsParseObjectGet(parameter) && parameter.Object is ParameterExpression))
                    {
                        var genericContains = ContainsMethod.MakeGenericMethod(parameter.Type);
                        return(Expression.Call(genericContains, collection, parameter));
                    }

                    var target  = new ObjectNormalizer().Visit(collection) as MethodCallExpression;
                    var element = node.Arguments[parameterIndex];
                    if (target != null && (IsParseObjectGet(target) && target.Object is ParameterExpression))
                    {
                        var genericContains = ContainsMethod.MakeGenericMethod(element.Type);
                        return(Expression.Call(genericContains, target, element));
                    }
                }

                // Convert obj["foo.bar"].ContainsKey("baz") into obj.ContainsKey("foo.bar.baz")
                if (node.Method.Name == "ContainsKey" &&
                    node.Method.ReturnType == typeof(bool) &&
                    node.Method.GetParameters().Length == 1)
                {
                    var        getter = new ObjectNormalizer().Visit(node.Object) as MethodCallExpression;
                    Expression target = null;
                    string     path   = null;
                    if (getter != null && (IsParseObjectGet(getter) && getter.Object is ParameterExpression))
                    {
                        target = getter.Object;
                        path   = GetValue(getter.Arguments[0]) + "." + GetValue(node.Arguments[0]);
                        return(Expression.Call(ContainsKeyMethod, target, Expression.Constant(path)));
                    }
                    else if (node.Object is ParameterExpression)
                    {
                        target = node.Object;
                        path   = GetValue(node.Arguments[0]) as string;
                    }

                    if (target != null && path != null)
                    {
                        return(Expression.Call(ContainsKeyMethod, target, Expression.Constant(path)));
                    }
                }

                return(base.VisitMethodCall(node));
            }
Exemple #8
0
            /// <summary>
            /// If a ! operator is used, this removes the ! and instead calls the equivalent
            /// function (so e.g. == becomes !=, &lt; becomes &gt;=, Contains becomes NotContains)
            /// </summary>
            protected override Expression VisitUnary(UnaryExpression node)
            {
                // Normalizes inversion
                if (node.NodeType == ExpressionType.Not)
                {
                    var visitedOperand = Visit(node.Operand);
                    var binaryOperand  = visitedOperand as BinaryExpression;
                    if (binaryOperand != null)
                    {
                        switch (binaryOperand.NodeType)
                        {
                        case ExpressionType.GreaterThan:
                            return(Expression.LessThanOrEqual(binaryOperand.Left, binaryOperand.Right));

                        case ExpressionType.GreaterThanOrEqual:
                            return(Expression.LessThan(binaryOperand.Left, binaryOperand.Right));

                        case ExpressionType.LessThan:
                            return(Expression.GreaterThanOrEqual(binaryOperand.Left, binaryOperand.Right));

                        case ExpressionType.LessThanOrEqual:
                            return(Expression.GreaterThan(binaryOperand.Left, binaryOperand.Right));

                        case ExpressionType.Equal:
                            return(Expression.NotEqual(binaryOperand.Left, binaryOperand.Right));

                        case ExpressionType.NotEqual:
                            return(Expression.Equal(binaryOperand.Left, binaryOperand.Right));
                        }
                    }

                    var methodCallOperand = visitedOperand as MethodCallExpression;
                    if (methodCallOperand != null)
                    {
                        if (methodCallOperand.Method.IsGenericMethod)
                        {
                            if (methodCallOperand.Method.GetGenericMethodDefinition() == ContainsMethod)
                            {
                                var genericNotContains = NotContainsMethod.MakeGenericMethod(
                                    methodCallOperand.Method.GetGenericArguments());
                                return(Expression.Call(genericNotContains, methodCallOperand.Arguments.ToArray()));
                            }

                            if (methodCallOperand.Method.GetGenericMethodDefinition() == NotContainsMethod)
                            {
                                var genericContains = ContainsMethod.MakeGenericMethod(
                                    methodCallOperand.Method.GetGenericArguments());
                                return(Expression.Call(genericContains, methodCallOperand.Arguments.ToArray()));
                            }
                        }

                        if (methodCallOperand.Method == ContainsKeyMethod)
                        {
                            return(Expression.Call(NotContainsKeyMethod, methodCallOperand.Arguments.ToArray()));
                        }

                        if (methodCallOperand.Method == NotContainsKeyMethod)
                        {
                            return(Expression.Call(ContainsKeyMethod, methodCallOperand.Arguments.ToArray()));
                        }
                    }
                }

                return(base.VisitUnary(node));
            }
        private static IQueryable <TSource> CallGenericWhereContainsMethod <TSource>(IQueryable <TSource> source, BaseFilterQuery filter)
        {
            var concreteType = typeof(TSource);
            var property     = concreteType.GetProperty(filter.Attribute.InternalAttributeName);

            try
            {
                var propertyValues         = filter.PropertyValue.Split(QueryConstants.COMMA);
                ParameterExpression entity = Expression.Parameter(concreteType, "entity");
                MemberExpression    member;
                if (filter.IsAttributeOfRelationship)
                {
                    var relation = Expression.PropertyOrField(entity, filter.Relationship.InternalRelationshipName);

                    // Intercept the call if the relationship is type of "HasMany"
                    if (typeof(IEnumerable).IsAssignableFrom(relation.Type))
                    {
                        // Create the lambda using "Any" extension method
                        var callExpr = BuildAnyCall(relation,
                                                    relation.Type.GenericTypeArguments[0],
                                                    filter);
                        var lambda = Expression.Lambda <Func <TSource, bool> >(callExpr, entity);
                        return(source.Where(lambda));
                    }

                    member = Expression.Property(relation, filter.Attribute.InternalAttributeName);
                }
                else
                {
                    member = Expression.Property(entity, filter.Attribute.InternalAttributeName);
                }

                var method = ContainsMethod.MakeGenericMethod(member.Type);
                var obj    = TypeHelper.ConvertListType(propertyValues, member.Type);

                if (filter.FilterOperation == FilterOperations.@in)
                {
                    // Where(i => arr.Contains(i.column))
                    var contains = Expression.Call(method, new Expression[] { Expression.Constant(obj), member });
                    var lambda   = Expression.Lambda <Func <TSource, bool> >(contains, entity);

                    return(source.Where(lambda));
                }
                if (filter.FilterOperation == FilterOperations.nin)
                {
                    // Where(i => !arr.Contains(i.column))
                    var notContains = Expression.Not(Expression.Call(method, new Expression[] { Expression.Constant(obj), member }));
                    var lambda      = Expression.Lambda <Func <TSource, bool> >(notContains, entity);

                    return(source.Where(lambda));
                }
                //if (filter.FilterOperation == FilterOperations.all)
                //{
                //    // Where(i => !arr.Contains(i.column))
                //    var notContains = Expression.Not(Expression.Call(method, new Expression[] { Expression.(obj), member }));
                //    var lambda = Expression.Lambda<Func<TSource, bool>>(notContains, entity);

                //    return source.Where(lambda);
                //}
                return(null);
            }
            catch (FormatException)
            {
                throw new JsonApiException(400, $"Could not cast {filter.PropertyValue} to {property.PropertyType.Name}");
            }
        }