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); } }