Exemplo n.º 1
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            if ((node.Method.DeclaringType == typeof(string)) &&
                (node.Method.CallingConvention & System.Reflection.CallingConventions.HasThis) == System.Reflection.CallingConventions.HasThis &&
                node.Arguments.Count == 1)
            {
                Expression objectExpression   = this.Visit(node.Object);
                Expression argumentExpression = this.Visit(node.Arguments[0]);
                Expression substringExpression;

                switch (node.Method.Name)
                {
                case "StartsWith":
                    substringExpression = LdapExpressionFactory.Substring(false, new[] { argumentExpression }, true);
                    break;

                case "EndsWith":
                    substringExpression = LdapExpressionFactory.Substring(true, new[] { argumentExpression }, false);
                    break;

                case "Contains":
                    substringExpression = LdapExpressionFactory.Substring(true, new[] { argumentExpression }, true);
                    break;

                default:
                    return(base.VisitMethodCall(node));
                }

                return(Expression.Equal(objectExpression, substringExpression));
            }
            else
            {
                return(base.VisitMethodCall(node));
            }
        }
        protected override Expression VisitBinary(BinaryExpression node)
        {
            // Note that we're turning shortcutting operators into, well, not.
            switch (node.NodeType)
            {
            case ExpressionType.And:
            case ExpressionType.AndAlso:
                if (node.Left.Type == typeof(bool) && node.Right.Type == typeof(bool))
                {
                    return(this.Visit(LdapExpressionFactory.And(new[] { node.Left, node.Right })));
                }
                break;

            case ExpressionType.Or:
            case ExpressionType.OrElse:
                if (node.Left.Type == typeof(bool) && node.Right.Type == typeof(bool))
                {
                    return(this.Visit(LdapExpressionFactory.Or(new[] { node.Left, node.Right })));
                }
                break;

            default:
                break;
            }
            return(base.VisitBinary(node));
        }
        protected override Expression VisitBinary(BinaryExpression node)
        {
            Expression result = base.VisitBinary(node);

            node = result as BinaryExpression;
            if (node == null)
            {
                return(result);
            }

            switch (node.NodeType)
            {
            case ExpressionType.Equal:
                if (node.Right.IsConstantNullOrEmpty())
                {
                    return(Expression.Not(LdapExpressionFactory.Present(node.Left)));
                }
                if (node.Right.NodeType == (ExpressionType)LdapExpressionType.Substring)
                {
                    SubstringExpression substring = node.Right as SubstringExpression;

                    /* If it's a substring expression with no parts to it, it's of one of the following forms:
                     * X=*.  X=*.*  X=.*  X=.
                     * (where the dot represents the empty parts list).
                     * In the first three cases, this translates to Present(X) expression;
                     * in the last one, to Not(Present(X)).  */
                    if (substring.Parts.Count == 0)
                    {
                        if (substring.WildcardAtStart || substring.WildcardAtEnd)
                        {
                            return(LdapExpressionFactory.Present(node.Left));
                        }
                        else
                        {
                            return(Expression.Not(LdapExpressionFactory.Present(node.Left)));
                        }
                    }
                }
                break;
            }

            return(node);
        }
        protected override Expression VisitBinary(BinaryExpression node)
        {
            Expression left  = this.Visit(node.Left);
            Expression right = this.Visit(node.Right);

            if (node.NodeType == ExpressionType.Equal &&
                left.NodeType == (ExpressionType)LdapExpressionType.Attribute &&
                right.NodeType == ExpressionType.Constant
                )
            {
                ConstantExpression constant = (ConstantExpression)right;
                if (constant.Value == null)
                {
                    return(Expression.Not(LdapExpressionFactory.Present(left)));
                }
            }

            return(node.Update(left, node.Conversion, right));
        }
        protected override Expression VisitNary(NaryExpression node)
        {
            Expression result = base.VisitNary(node);

            node = result as NaryExpression;
            if (node == null)
            {
                return(result);
            }

            switch ((LdapExpressionType)node.NodeType)
            {
            case LdapExpressionType.And:
                // (& X, false) -> false
                if (node.Clauses.Any(c => c.IsConstant(false)))
                {
                    return(False);
                }
                // If any of the sub-clauses is true, then the 'and' is not affected by them.
                var andClauses = node.Clauses.Where(c => !c.IsConstant(true));
                switch (andClauses.Count())
                {
                case 0:
                    // This is trivially true.
                    // (& true) -> true
                    return(True);

                case 1:
                    // Just return the sub-clause.
                    // (& true, X) -> X
                    return(andClauses.First());

                default:
                    if (andClauses.Count() == node.Clauses.Count)
                    {
                        // No changes
                        // (& X, Y) -> (& X, Y)
                        return(node);
                    }
                    else
                    {
                        // (& true, X, Y) -> (& X, Y)
                        //return node.Update( andClauses );
                        return(LdapExpressionFactory.And(andClauses));
                    }
                }

            case LdapExpressionType.Or:
                // (| X, true) -> true
                if (node.Clauses.Any(c => c.IsConstant(true)))
                {
                    return(True);
                }
                // If any of the sub-clauses is false, then the 'or' is not affected by them.
                var orClauses = node.Clauses.Where(c => !c.IsConstant(false));
                switch (orClauses.Count())
                {
                case 0:
                    // This is trivially false
                    // (| false) -> false
                    return(False);

                case 1:
                    // Just return the sub-clause.
                    // (| false, X) -> X
                    return(orClauses.First());

                default:
                    if (orClauses.Count() == node.Clauses.Count)
                    {
                        // No changes
                        // (| X, Y) -> (| X, Y)
                        return(node);
                    }
                    else
                    {
                        // (| X, Y, false) -> (| X, Y)
                        //return node.Update( orClauses );
                        return(LdapExpressionFactory.And(orClauses));
                    }
                }

            default:
                // Some other type of Nary expression...
                return(node);
            }
        }