public override Expression HandleOperation(
        QueryableFilterContext context,
        IFilterOperationField field,
        IValueNode value,
        object?parsedValue)
    {
        if (context.RuntimeTypes.Count > 0 &&
            context.RuntimeTypes.Peek().TypeArguments is { Count : > 0 } args&&
            parsedValue is bool parsedBool)
        {
            Expression?property = context.GetInstance();

            Expression expression;
            if (parsedBool)
            {
                expression = FilterExpressionBuilder.Any(args[0].Source, property);
            }
            else
            {
                expression = FilterExpressionBuilder.Not(
                    FilterExpressionBuilder.Any(args[0].Source, property));
            }

            if (context.InMemory)
            {
                expression = FilterExpressionBuilder.NotNullAndAlso(property, expression);
            }

            return(expression);
        }

        throw ThrowHelper.Filtering_CouldNotParseValue(this, value, field.Type, field);
    }
    /// <summary>
    /// Converts the value of the <paramref name="parsedValue"/> into the needed runtime type
    /// </summary>
    /// <param name="node">The value node to parse</param>
    /// <param name="parsedValue">The parsed value of the <paramref name="node"/></param>
    /// <param name="type">
    /// The type of the field that the <paramref name="node"/> was defined
    /// </param>
    /// <param name="context">The visitor context</param>
    /// <returns>The converted value</returns>
    protected object?ParseValue(
        IValueNode node,
        object?parsedValue,
        IType type,
        QueryableFilterContext context)
    {
        if (parsedValue is null)
        {
            return(parsedValue);
        }

        Type returnType = context.RuntimeTypes.Peek().Source;

        if (type.IsListType())
        {
            Type elementType = type.ElementType().ToRuntimeType();

            if (returnType != elementType)
            {
                Type listType = typeof(List <>).MakeGenericType(returnType);
                parsedValue = TypeConverter.Convert(typeof(object), listType, parsedValue) ??
                              throw ThrowHelper.FilterConvention_CouldNotConvertValue(node);
            }

            return(parsedValue);
        }

        if (!returnType.IsInstanceOfType(parsedValue))
        {
            parsedValue = TypeConverter.Convert(typeof(object), returnType, parsedValue) ??
                          throw ThrowHelper.FilterConvention_CouldNotConvertValue(node);
        }

        return(parsedValue);
    }
 protected override Expression HandleListOperation(
     QueryableFilterContext context,
     IFilterField field,
     ObjectFieldNode node,
     Type closureType,
     LambdaExpression lambda) =>
 FilterExpressionBuilder.Any(closureType, context.GetInstance(), lambda);
    public override Expression HandleOperation(
        QueryableFilterContext context,
        IFilterOperationField field,
        IValueNode value,
        object parsedValue)
    {
        // We get the instance of the context. This is the expression path to the propert
        // e.g. ~> y.Street
        Expression property = context.GetInstance();

        // the parsed value is what was specified in the query
        // e.g. ~> eq: "221B Baker Street"
        if (parsedValue is string str)
        {
            // Creates and returnes the operation
            // e.g. ~> y.Street.ToLower().Contains("221b baker street")
            // return Expression.Lambda<Func<string, bool>>(
            // Expression.Call(Expression.Call(property, _toLower), _contains, Expression.Constant(str.ToLower()))
            // );
            return(Expression.Equal(
                       property, Expression.Constant(str.ToLower())
                       ));
        }

        // Something went wrong 😱
        throw new InvalidOperationException();
    }
Beispiel #5
0
 public override Expression HandleOperation(
     QueryableFilterContext context,
     IFilterOperationField field,
     IValueNode value,
     object parsedValue)
 {
     throw new System.NotImplementedException();
 }
    public override Expression HandleOperation(
        QueryableFilterContext context,
        IFilterOperationField field,
        IValueNode value,
        object parsedValue)
    {
        Expression property = context.GetInstance();

        return(FilterExpressionBuilder.Equals(property, parsedValue));
    }
Beispiel #7
0
    public override Expression HandleOperation(
        QueryableFilterContext context,
        IFilterOperationField field,
        IValueNode value,
        object parsedValue)
    {
        Expression property = context.GetInstance();

        return(FilterExpressionBuilder.In(
                   property,
                   context.RuntimeTypes.Peek().Source,
                   parsedValue));
    }
Beispiel #8
0
        public override Expression HandleOperation(QueryableFilterContext context, IFilterOperationField field, IValueNode value, object?parsedValue)
        {
            Expression property = context.GetInstance();

            if (parsedValue is string fieldValue)
            {
                //Compiles to:
                //false == property.ToLower().Contains(input.ToLower());

                return(Expression.Equal(Expression.Constant(false), Expression.Call(Expression.Call(property, Expressions.ToLower), Expressions.Contains, Expression.Constant(fieldValue.ToLower()))));
            }

            throw new InvalidOperationException();
        }
Beispiel #9
0
        public Func <T, bool> Build <T>(IValueNode filter)
        {
            var visitorContext = new QueryableFilterContext(_inputType, true);
            var visitor        = new FilterVisitor <QueryableFilterContext, Expression>(
                new QueryableCombinator());

            visitor.Visit(filter, visitorContext);

            if (visitorContext.TryCreateLambda(out Expression <Func <T, bool> >?where))
            {
                return(where.Compile());
            }

            throw new InvalidOperationException();
        }
Beispiel #10
0
    /// <summary>
    /// Tries to build the a typed expression based on the items that are stored on the scope
    /// </summary>
    /// <param name="context">the context</param>
    /// <param name="expression">The query that was build</param>
    /// <typeparam name="T">The generic type of the expression</typeparam>
    /// <returns>True in case the query has been build successfully, otherwise false</returns>
    public static bool TryCreateLambda <T>(
        this QueryableFilterContext context,
        [NotNullWhen(true)] out Expression <T>?expression)
    {
        if (context.Scopes.TryPeekElement(out FilterScope <Expression>?scope) &&
            scope is QueryableScope closure &&
            closure.Level.TryPeekElement(out Queue <Expression>?levels) &&
            levels.TryPeekElement(out Expression? level))
        {
            expression = Expression.Lambda <T>(level, closure.Parameter);
            return(true);
        }

        expression = null;
        return(false);
    }
Beispiel #11
0
    public override Expression HandleOperation(
        QueryableFilterContext context,
        IFilterOperationField field,
        IValueNode value,
        object?parsedValue)
    {
        Expression property = context.GetInstance();

        parsedValue = ParseValue(value, parsedValue, field.Type, context);

        if (parsedValue is null)
        {
            throw ThrowHelper.Filtering_CouldNotParseValue(this, value, field.Type, field);
        }

        return(FilterExpressionBuilder.LowerThanOrEqual(property, parsedValue));
    }
Beispiel #12
0
        public override Expression HandleOperation(
            QueryableFilterContext context,
            IFilterOperationField field,
            IValueNode value,
            object parsedValue)
        {
            // We get the instance of the context. This is the expression path to the propert
            // e.g. ~> y.Street
            Expression property = context.GetInstance();

            // the parsed value is what was specified in the query
            // e.g. ~> eq: "221B Baker Street"
            if (parsedValue is string str)
            {
                // Creates and returns the operation
                // e.g. ~> y.Street.ToLower() == "221b baker street"

                //MethodInfo contains = typeof(string).GetMethod("Contains");
                //var bodyLike = Expression.Call(expressionParameter, contains, Expression.Constant(fieldValue, prop.PropertyType));
                //return Expression.Lambda<Func<T, bool>>(bodyLike, parameter);

                //var lowerString = Expression.Call(property, _toLower).ToString();
                //var lowerSearchTerm = str.ToLower();

//        return lowerString.Contains(lowerSearchTerm, StringComparison.InvariantCultureIgnoreCase);

                return(Expression.Call(
                           Expression.Call(property, _toLower),
                           "Contains",
                           Type.EmptyTypes,
                           Expression.Constant(str.ToLower())
                           ));

                //return Expression.Equal(
                //  Expression.Call(property, _toLower),
                //  Expression.Constant(str.ToLower()));
            }
            // Something went wrong 😱
            throw new InvalidOperationException();
        }
        protected override bool TryHandleOperation(
            QueryableFilterContext context,
            IFilterOperationField field,
            ObjectFieldNode node,
            [NotNullWhen(true)] out Expression?result)
        {
            if (TryGetParameter(field, node.Value, GeometryFieldName, out Geometry g))
            {
                if (TryGetParameter(field, node.Value, BufferFieldName, out double buffer))
                {
                    result = ExpressionBuilder.Overlaps(
                        context.GetInstance(),
                        ExpressionBuilder.Buffer(g, buffer));
                    return(true);
                }

                result = ExpressionBuilder.Overlaps(context.GetInstance(), g);
                return(true);
            }

            result = null;
            return(false);
        }
Beispiel #14
0
 /// <summary>
 /// Reads the current closure from the context
 /// </summary>
 /// <param name="context">The context</param>
 /// <returns>The current closure</returns>
 public static QueryableScope GetClosure(
     this QueryableFilterContext context) =>
 (QueryableScope)context.GetScope();