Exemplo n.º 1
0
        public override LambdaExpression VisitValPathOperatorExp(ScimFilterParser.ValPathOperatorExpContext 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));
        }