Beispiel #1
0
//        public override LambdaExpression VisitNotExp(ScimFilterParser.NotExpContext context)
//        {
//            var predicate = Visit(context.expression());

//            var parameter = Expression.Parameter(typeof(TResource));
//            var resultBody = Expression.Not(Expression.Invoke(predicate, parameter));

//            return Expression.Lambda<Func<TResource, bool>>(resultBody, parameter);
//        }

        public override LambdaExpression VisitOperatorExp(ScimFilterParser.OperatorExpContext context)
        {
            var argument           = Expression.Parameter(typeof(TResource));
            var attrPathExpression = Visit(context.attrPath());
            var operatorToken      = context.COMPAREOPERATOR().GetText().ToLower();
            var valueToken         = context.VALUE().GetText().Trim('"');

            var isEnumerable = attrPathExpression.ReturnType.IsNonStringEnumerable();

            var left = Expression.TryCatch(
                Expression.Block(Expression.Invoke(attrPathExpression, argument)),
                Expression.Catch(
                    typeof(NullReferenceException),
                    Expression.Constant(attrPathExpression.ReturnType.GetDefaultValue(), attrPathExpression.ReturnType))
                );

            if (isEnumerable &&
                attrPathExpression.ReturnType.IsGenericType &&
                typeof(MultiValuedAttribute).IsAssignableFrom(attrPathExpression.ReturnType.GetGenericArguments()[0]))
            {
                // we're filtering an enumerable of multivaluedattribute without a sub-attribute
                // therefore, we default to evaluating the .Value member

                var multiValuedAttributeType = attrPathExpression.ReturnType.GetGenericArguments()[0];
                var multiValuedAttribute     = Expression.Parameter(multiValuedAttributeType);
                var valueAttribute           = multiValuedAttributeType.GetProperty("Value", BindingFlags.Public | BindingFlags.Instance);
                var valueExpression          = Expression.TryCatch(
                    Expression.Block(Expression.Property(multiValuedAttribute, valueAttribute)),
                    Expression.Catch(
                        typeof(NullReferenceException),
                        Expression.Constant(valueAttribute.PropertyType.GetDefaultValue(), valueAttribute.PropertyType))
                    );

                var valueLambda = Expression.Lambda(
                    CreateBinaryExpression(valueExpression, operatorToken, valueToken),
                    multiValuedAttribute);

                var anyMethod    = MethodCache["any"].MakeGenericMethod(multiValuedAttributeType);
                var anyPredicate = Expression.TryCatch(
                    Expression.Block(
                        Expression.Call(
                            anyMethod,
                            new List <Expression>
                {
                    left,
                    valueLambda
                })),
                    Expression.Catch(typeof(ArgumentNullException), Expression.Constant(false)));

                return(Expression.Lambda(anyPredicate, argument));
            }

            return(Expression.Lambda <Func <TResource, bool> >(
                       CreateBinaryExpression(left, operatorToken, valueToken),
                       argument));
        }
Beispiel #2
0
//        public override LambdaExpression VisitNotExp(ScimFilterParser.NotExpContext context)
//        {
//            var predicate = Visit(context.expression());

//            var parameter = Expression.Parameter(typeof(TResource));
//            var resultBody = Expression.Not(Expression.Invoke(predicate, parameter));

//            return Expression.Lambda<Func<TResource, bool>>(resultBody, parameter);
//        }

        public override LambdaExpression VisitOperatorExp(ScimFilterParser.OperatorExpContext context)
        {
            var propertyNameToken = context.FIELD().GetText();
            var operatorToken     = context.COMPAREOPERATOR().GetText().ToLower();
            var valueToken        = context.VALUE().GetText().Trim('"');

            var property = PropertyCache
                           .GetOrAdd(
                typeof(TResource),
                type =>
                type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .ToDictionary(pi => pi.Name, pi => pi, StringComparer.OrdinalIgnoreCase))[propertyNameToken];

            if (property == null)
            {
                throw new Exception("ERROR");                   // TODO: (DG) make proper error
            }
            var isEnumerable = property.PropertyType.IsNonStringEnumerable();
            var argument     = Expression.Parameter(typeof(TResource));
            var left         = Expression.TryCatch(
                Expression.Block(Expression.Property(argument, property)),
                Expression.Catch(
                    typeof(NullReferenceException),
                    Expression.Constant(property.PropertyType.GetDefaultValue(), property.PropertyType))
                );

            if (isEnumerable &&
                property.PropertyType.IsGenericType &&
                typeof(MultiValuedAttribute).IsAssignableFrom(property.PropertyType.GetGenericArguments()[0]))
            {
                // we're filtering an enumerable of multivaluedattribute without a sub-attribute
                // therefore, we default to evaluating the .Value member

                var multiValuedAttributeType = property.PropertyType.GetGenericArguments()[0];
                var multiValuedAttribute     = Expression.Parameter(multiValuedAttributeType);
                var valueAttribute           = multiValuedAttributeType.GetProperty("Value", BindingFlags.Public | BindingFlags.Instance);
                var valueExpression          = Expression.TryCatch(
                    Expression.Block(Expression.Property(multiValuedAttribute, valueAttribute)),
                    Expression.Catch(
                        typeof(NullReferenceException),
                        Expression.Constant(valueAttribute.PropertyType.GetDefaultValue(), valueAttribute.PropertyType))
                    );

                var valueLambda = Expression.Lambda(
                    CreateBinaryExpression(valueExpression, valueAttribute, operatorToken, valueToken),
                    multiValuedAttribute);

                var anyMethod    = MethodCache["any"].MakeGenericMethod(multiValuedAttributeType);
                var anyPredicate = Expression.TryCatch(
                    Expression.Block(
                        Expression.Call(
                            anyMethod,
                            new List <Expression>
                {
                    left,
                    valueLambda
                })),
                    Expression.Catch(typeof(ArgumentNullException), Expression.Constant(false)));

                return(Expression.Lambda(anyPredicate, argument));
            }

            return(Expression.Lambda <Func <TResource, bool> >(
                       CreateBinaryExpression(left, property, operatorToken, valueToken),
                       argument));
        }