Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 5
0
        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);
        }