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 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 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 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) { if (invariantExpression) { return(base.VisitMemberAccess(expression)); } if (expression.Expression != lambdaParam) { if (expression.Member.DeclaringType == typeof(ISPModelMetaData) && ((expression.Expression.NodeType == ExpressionType.Call && ((MethodCallExpression)expression.Expression).Method == typeof(SPModelExtension).GetMethod("GetMetaData") && ((MethodCallExpression)expression.Expression).Arguments[0] == lambdaParam) || (expression.Expression.NodeType == ExpressionType.Convert && ((UnaryExpression)expression.Expression).Operand == lambdaParam))) { // allow non-direct field access on the ISPModelMetaData interface } else { Expression result = base.VisitMemberAccess(expression); if (expression.Member.DeclaringType.IsGenericType && expression.Member.DeclaringType.GetGenericTypeDefinition() == typeof(Nullable <>) && expression.Member.Name == "HasValue") { CamlExpression expr = currentScope.GetExpression(v => Caml.IsNotNull(v.FieldRef)); currentScope.Reset(); currentScope.Expression = expr; } return(result); } } currentScope.MemberType = expression.Type; currentScope.Member = expression.Member; currentScope.Field = default(SPModelQueryFieldInfo); currentScope.FieldAssociations = null; 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("Member '{0}' is not supported", GetMemberFullName(expression.Member))); } } else { currentScope.FieldAssociations = SPModelFieldAssociationCollection.GetByMember(expression.Member); foreach (SPFieldAttribute field in currentScope.FieldAssociations.Fields) { if (field.TypeAsString == "TaxonomyFieldType" || field.TypeAsString == "TaxonomyFieldTypeMulti") { builder.TaxonomyFields.Add(field.ListFieldInternalName); } } } if (builder.SelectExpression != null) { if (currentScope.Field.FieldRef != null) { builder.AddSelectProperty(currentScope.Field.FieldRef); } else if (currentScope.FieldAssociations.Queryable && expression.Member.MemberType == MemberTypes.Property && ((PropertyInfo)expression.Member).GetGetMethod().IsAbstract) { builder.AddSelectProperty(currentScope.FieldAssociations.Fields.First().ListFieldInternalName); } else { builder.SelectAllProperties = true; } } return(expression); }