protected override Expression VisitConditional(ConditionalExpression expression) { if (invariantExpression || builder.SelectExpression != null) { return(base.VisitConditional(expression)); } SPModelQueryExpressionScope currentScope = this.currentScope; SPModelQueryExpressionScope childScope = new SPModelQueryExpressionScope(this); CamlExpression condition, trueExpression, falseExpression; this.currentScope = childScope; VisitConditionalBranch(expression.Test); condition = childScope.Expression; childScope.Reset(); Visit(expression.IfTrue); trueExpression = childScope.Expression; childScope.Reset(); Visit(expression.IfFalse); falseExpression = childScope.Expression; currentScope.Expression = ((condition & trueExpression) | ((~condition) & falseExpression)); this.currentScope = currentScope; return(expression); }
protected override Expression VisitUnary(UnaryExpression expression) { SPModelQueryExpressionScope currentScope = stack.Peek(); SPModelQueryExpressionScope childScope = new SPModelQueryExpressionScope(this); stack.Push(childScope); Visit(expression.Operand); switch (expression.NodeType) { case ExpressionType.Not: currentScope.Expression = ~childScope.Expression; break; case ExpressionType.Convert: case ExpressionType.ConvertChecked: case ExpressionType.Quote: childScope.CopyTo(currentScope); break; default: throw new NotSupportedException(String.Format("The unary operator '{0}' is not supported", expression.NodeType)); } stack.Pop(); return(expression); }
protected override Expression VisitUnary(UnaryExpression expression) { if (invariantExpression || builder.SelectExpression != null) { return(base.VisitUnary(expression)); } SPModelQueryExpressionScope currentScope = this.currentScope; SPModelQueryExpressionScope childScope = new SPModelQueryExpressionScope(this); this.currentScope = childScope; Visit(expression.Operand); switch (expression.NodeType) { case ExpressionType.Not: currentScope.Expression = ~childScope.Expression; break; case ExpressionType.Convert: case ExpressionType.ConvertChecked: case ExpressionType.Quote: childScope.CopyTo(currentScope); break; default: throw new NotSupportedException(String.Format("Unary operator '{0}' is not supported", expression.NodeType)); } this.currentScope = currentScope; return(expression); }
public void CopyTo(SPModelQueryExpressionScope other) { CommonHelper.ConfirmNotNull(other, "other"); other.Expression = this.Expression; other.FieldAssociations = this.FieldAssociations; other.Field = this.Field; other.Member = this.Member; other.MemberType = this.MemberType; other.ParameterName = this.ParameterName; }
public void CopyTo(SPModelQueryExpressionScope other) { CommonHelper.ConfirmNotNull(other, "other"); other.Expression = this.Expression; other.FieldAssociations = this.FieldAssociations; other.Field = this.Field; other.Member = this.Member; other.MemberType = this.MemberType; other.IsValueDefined = this.IsValueDefined; other.definedValue = definedValue; }
protected override Expression VisitMethodCall(MethodCallExpression expression) { if (invariantExpression) { return(base.VisitMethodCall(expression)); } bool sameQueryable = expression.Method.DeclaringType == typeof(Queryable) && ContainsOrEquals(expression.Arguments[0], parameters[0]); if (builder.SelectExpression != null && !sameQueryable) { return(base.VisitMethodCall(expression)); } SPModelQueryExpressionScope currentScope = this.currentScope; try { SPModelQueryExpressionScope childScope = new SPModelQueryExpressionScope(this); this.currentScope = childScope; if (sameQueryable) { ValidateQueryableMethodCall(expression); ParameterExpression currentLambdaParam = lambdaParam; Visit(expression.Arguments[0]); currentScope.Expression = childScope.Expression; childScope.Reset(); currentScope.Expression += GetExpressionFromQueryableMethod(expression); lambdaParam = currentLambdaParam; return(expression); } if (expression.Method.DeclaringType == typeof(Enumerable) || expression.Method.DeclaringType.IsOf(typeof(ICollection <>))) { currentScope.Expression = GetExpressionFromEnumerableMethod(expression); return(expression); } if (expression.Method.DeclaringType == typeof(string)) { currentScope.Expression = GetExpressionFromStringMethod(expression); return(expression); } if (expression.Method.Name == "Equals" && expression.Arguments.Count == 1) { Visit(expression.Object); Visit(expression.Arguments[0]); currentScope.Expression = childScope.GetExpression((SPModelQueryExpressionScope.ExpressionGenerator)Caml.Equals); return(expression); } throw ThrowMethodNotSupported(expression.Method); } finally { this.currentScope = currentScope; } }
protected override Expression VisitTypeIs(TypeBinaryExpression expression) { SPModelQueryExpressionScope currentScope = stack.Peek(); try { SPModelDescriptor descriptor = SPModelDescriptor.Resolve(expression.TypeOperand); currentScope.Expression = descriptor.GetContentTypeExpression(manager.Descriptor); } catch (ArgumentException) { currentScope.Expression = Caml.False; } return(expression); }
public SPModelQueryExpressionTranslateResult Translate(Expression expression) { CommonHelper.ConfirmNotNull(expression, "expression"); SPModelQueryExpressionScope currentScope = new SPModelQueryExpressionScope(this); stack.Push(currentScope); Expression evaledExpression = PartialEvaluator.Eval(expression, CanBeEvaluatedLocally); Visit(evaledExpression); result.Expression = currentScope.Expression; return(result); }
protected override Expression VisitConditional(ConditionalExpression expression) { if (expression.Test.NodeType == ExpressionType.Constant) { if (true.Equals(((ConstantExpression)expression.Test).Value)) { Visit(expression.IfTrue); } else { Visit(expression.IfFalse); } } else { SPModelQueryExpressionScope currentScope = stack.Peek(); SPModelQueryExpressionScope childScope = new SPModelQueryExpressionScope(this); CamlExpression condition, trueExpression, falseExpression; stack.Push(childScope); Visit(expression.Test); condition = childScope.Expression; childScope.Reset(); Visit(expression.IfTrue); trueExpression = childScope.Expression; childScope.Reset(); Visit(expression.IfFalse); falseExpression = childScope.Expression; currentScope.Expression = ((condition & trueExpression) | ((~condition) & falseExpression)); stack.Pop(); } return(expression); }
protected override Expression VisitBinary(BinaryExpression expression) { SPModelQueryExpressionScope currentScope = stack.Peek(); SPModelQueryExpressionScope childScope = new SPModelQueryExpressionScope(this); SPModelQueryExpressionScope childScopeTwo = null; stack.Push(childScope); Visit(expression.Left); if (expression.NodeType == ExpressionType.AndAlso || expression.NodeType == ExpressionType.OrElse) { stack.Pop(); childScopeTwo = new SPModelQueryExpressionScope(this); stack.Push(childScopeTwo); } Visit(expression.Right); switch (expression.NodeType) { case ExpressionType.AndAlso: currentScope.Expression = childScope.Expression & childScopeTwo.Expression; break; case ExpressionType.OrElse: currentScope.Expression = childScope.Expression | childScopeTwo.Expression; break; case ExpressionType.Equal: if (childScope.Value == null) { currentScope.Expression = childScope.GetExpression(s => HandleNullExpression(s, false)); } else { currentScope.Expression = childScope.GetExpression((SPModelQueryExpressionScope.ExpressionGenerator)Caml.Equals); } break; case ExpressionType.NotEqual: if (childScope.Value == null) { currentScope.Expression = childScope.GetExpression(s => HandleNullExpression(s, true)); } else { currentScope.Expression = childScope.GetExpression(Caml.NotEquals); } break; case ExpressionType.LessThan: currentScope.Expression = childScope.GetExpression(Caml.LessThan); break; case ExpressionType.LessThanOrEqual: currentScope.Expression = childScope.GetExpression(Caml.LessThanOrEqual); break; case ExpressionType.GreaterThan: currentScope.Expression = childScope.GetExpression(Caml.GreaterThan); break; case ExpressionType.GreaterThanOrEqual: currentScope.Expression = childScope.GetExpression(Caml.GreaterThanOrEqual); break; default: throw new NotSupportedException(String.Format("The binary operator '{0}' is not supported", expression.NodeType)); } stack.Pop(); return(expression); }
protected override Expression VisitMethodCall(MethodCallExpression expression) { SPModelQueryExpressionScope currentScope = stack.Peek(); SPModelQueryExpressionScope childScope = new SPModelQueryExpressionScope(this); stack.Push(childScope); if (expression.Method.DeclaringType == typeof(Queryable)) { Visit(expression.Arguments[0]); currentScope.Expression = childScope.Expression; childScope.Reset(); switch (expression.Method.Name) { case "Where": if (expression.Arguments.Count == 3) { throw new NotSupportedException(String.Format("The method '{0}' with element's index used in the logic is not supported", expression.Method.Name)); } Visit(expression.Arguments[1]); currentScope.Expression += childScope.Expression; break; case "Union": if (expression.Arguments.Count == 3) { throw new NotSupportedException(String.Format("The method '{0}' with element's index used in the logic is not supported", expression.Method.Name)); } Visit(expression.Arguments[1]); currentScope.Expression |= childScope.Expression; break; case "Count": result.ExecuteMode = Enum <SPModelQueryExecuteMode> .Parse(expression.Method.Name); if (expression.Arguments.Count > 1) { Visit(expression.Arguments[1]); currentScope.Expression += childScope.Expression; } break; case "All": case "Any": case "FirstOrDefault": case "First": case "SingleOrDefault": case "Single": case "ElementAtOrDefault": case "ElementAt": result.ExecuteMode = Enum <SPModelQueryExecuteMode> .Parse(expression.Method.Name); if (result.ExecuteMode == SPModelQueryExecuteMode.ElementAt || result.ExecuteMode == SPModelQueryExecuteMode.ElementAtOrDefault) { result.Limit += Math.Max(0, Convert.ToInt32(((ConstantExpression)expression.Arguments[1]).Value)); } else if (result.ExecuteMode == SPModelQueryExecuteMode.Single || result.ExecuteMode == SPModelQueryExecuteMode.SingleOrDefault) { result.Limit = 2; } else { result.Limit = 1; } if (expression.Arguments.Count > 1) { Visit(expression.Arguments[1]); currentScope.Expression += childScope.Expression; } break; case "Take": result.Limit = Math.Max(0, Convert.ToInt32(((ConstantExpression)expression.Arguments[1]).Value)); break; case "Skip": result.Offset = Math.Max(0, Convert.ToInt32(((ConstantExpression)expression.Arguments[1]).Value)); break; case "OrderBy": case "ThenBy": if (expression.Arguments.Count == 3) { throw new NotSupportedException(String.Format("The method '{0}' with specified comparer is not supported", expression.Method.Name)); } Visit(expression.Arguments[1]); currentScope.Expression += childScope.GetExpression(s => Caml.OrderByAscending(s.FieldRef), true); break; case "OrderByDescending": case "ThenByDescending": if (expression.Arguments.Count == 3) { throw new NotSupportedException(String.Format("The method '{0}' with specified comparer is not supported", expression.Method.Name)); } Visit(expression.Arguments[1]); currentScope.Expression += childScope.GetExpression(s => Caml.OrderByDescending(s.FieldRef), true); break; case "Select": result.SelectExpression = (LambdaExpression)StripQuotes(expression.Arguments[1]); break; case "OfType": result.ModelType = expression.Method.GetGenericArguments()[0]; break; default: throw new NotSupportedException(String.Format("The method '{0}' is not supported", expression.Method.Name)); } } else if (expression.Method.DeclaringType == typeof(Enumerable)) { switch (expression.Method.Name) { case "Contains": if (expression.Arguments.Count == 3) { throw new NotSupportedException(String.Format("The method '{0}' with specified comparer is not supported", expression.Method.Name)); } Visit(expression.Arguments[0]); Visit(expression.Arguments[1]); if (childScope.Value is IEnumerable) { if (((IEnumerable)childScope.Value).OfType <object>().Any()) { currentScope.Expression = childScope.GetExpression(Caml.EqualsAny); } else { currentScope.Expression = CamlExpression.False; } } else { currentScope.Expression = childScope.GetExpression(Caml.Includes); } break; default: throw new NotSupportedException(String.Format("The method '{0}' is not supported", expression.Method.Name)); } } else if (expression.Method.DeclaringType == typeof(String)) { Visit(expression.Object); switch (expression.Method.Name) { case "StartsWith": Visit(expression.Arguments[0]); currentScope.Expression = childScope.GetExpression(s => Caml.BeginsWith(s.FieldRef, (childScope.Value ?? String.Empty).ToString())); break; default: throw new NotSupportedException(String.Format("The method '{0}' is not supported", expression.Method.Name)); } } else if (expression.Method.DeclaringType.IsOf(typeof(ICollection <>))) { switch (expression.Method.Name) { case "Contains": Visit(expression.Object); Visit(expression.Arguments[0]); if (childScope.Value is IEnumerable) { if (((IEnumerable)childScope.Value).OfType <object>().Any()) { currentScope.Expression = childScope.GetExpression(Caml.EqualsAny); } else { currentScope.Expression = CamlExpression.False; } } else { currentScope.Expression = childScope.GetExpression(Caml.Includes); } break; default: throw new NotSupportedException(String.Format("The method '{0}' is not supported", expression.Method.Name)); } } else if (expression.Method.Name == "Equals" && expression.Arguments.Count == 1) { Visit(expression.Object); Visit(expression.Arguments[0]); currentScope.Expression = childScope.GetExpression((SPModelQueryExpressionScope.ExpressionGenerator)Caml.Equals); } else { throw new NotSupportedException(String.Format("The method '{0}' is not supported", expression.Method.Name)); } stack.Pop(); return(expression); }
protected override Expression VisitMemberAccess(MemberExpression expression) { SPModelQueryExpressionScope currentScope = stack.Peek(); switch (expression.Expression.NodeType) { case ExpressionType.Parameter: case ExpressionType.MemberAccess: case ExpressionType.Convert: case ExpressionType.Call: if (expression.Member.DeclaringType == typeof(ISPModelMetaData)) { switch (expression.Member.Name) { case "ID": currentScope.Field = SPModelQueryFieldInfo.ID; break; case "UniqueId": currentScope.Field = SPModelQueryFieldInfo.UniqueId; break; case "FileRef": currentScope.Field = SPModelQueryFieldInfo.FileRef; break; case "FileLeafRef": currentScope.Field = SPModelQueryFieldInfo.FileLeafRef; break; case "LastModified": currentScope.Field = SPModelQueryFieldInfo.LastModified; break; case "CheckOutUserID": currentScope.Field = SPModelQueryFieldInfo.CheckOutUserID; break; default: throw new NotSupportedException(String.Format("The member '{0}' is not supported", expression.Member.Name)); } } else if (expression.Member.DeclaringType == typeof(TaxonomyItem) || expression.Member.DeclaringType == typeof(SPPrincipal)) { switch (expression.Member.Name) { case "Id": case "ID": Visit(expression.Expression); break; default: throw new NotSupportedException(String.Format("The member '{0}' is not supported", expression.Member.Name)); } } else { currentScope.MemberType = expression.Type; currentScope.Member = expression.Member; currentScope.FieldAssociations = SPModelFieldAssociationCollection.GetByMember(expression.Member); } break; default: throw new NotSupportedException(String.Format("The member '{0}' is not supported", expression.Member.Name)); } return(expression); }
private SPModelQueryExpressionVisitor(ISPModelManagerInternal manager, ReadOnlyCollection <ParameterExpression> parameters) { this.manager = manager; this.parameters = parameters; this.currentScope = new SPModelQueryExpressionScope(this); }
protected override Expression VisitBinary(BinaryExpression expression) { if (invariantExpression || builder.SelectExpression != null) { return(base.VisitBinary(expression)); } SPModelQueryExpressionScope currentScope = this.currentScope; SPModelQueryExpressionScope childScope = new SPModelQueryExpressionScope(this); SPModelQueryExpressionScope childScopeTwo = null; this.currentScope = childScope; if (expression.NodeType == ExpressionType.AndAlso || expression.NodeType == ExpressionType.OrElse) { childScopeTwo = new SPModelQueryExpressionScope(this); VisitConditionalBranch(expression.Left); this.currentScope = childScopeTwo; VisitConditionalBranch(expression.Right); } else { Visit(expression.Left); Visit(expression.Right); } switch (expression.NodeType) { case ExpressionType.AndAlso: currentScope.Expression = childScope.Expression & childScopeTwo.Expression; break; case ExpressionType.OrElse: currentScope.Expression = childScope.Expression | childScopeTwo.Expression; break; case ExpressionType.Equal: currentScope.Expression = childScope.GetExpression(s => HandleEqualityComparison(s, CamlBinaryOperator.Eq)); break; case ExpressionType.NotEqual: currentScope.Expression = childScope.GetExpression(s => HandleEqualityComparison(s, CamlBinaryOperator.Neq)); break; case ExpressionType.LessThan: currentScope.Expression = childScope.GetExpression(Caml.LessThan); break; case ExpressionType.LessThanOrEqual: currentScope.Expression = childScope.GetExpression(Caml.LessThanOrEqual); break; case ExpressionType.GreaterThan: currentScope.Expression = childScope.GetExpression(Caml.GreaterThan); break; case ExpressionType.GreaterThanOrEqual: currentScope.Expression = childScope.GetExpression(Caml.GreaterThanOrEqual); break; default: throw new NotSupportedException(String.Format("Binary operator '{0}' is not supported", expression.NodeType)); } this.currentScope = currentScope; return(expression); }