/// <summary>
 /// 访问指定的方法
 /// </summary>
 /// <param name="theEntityType">实体的类型</param>
 /// <param name="m">访问方法调用相关的表达式</param>
 /// <param name="tableAlias">表的别名</param>
 /// <param name="colConditionParts">存储条件节点的栈</param>
 /// <param name="colParameterNames">存储参数名称的列表</param>
 /// <param name="colDbTypes">存储数据库字段类型的列表</param>
 /// <param name="colArguments">存储条件值的列表</param>
 public static void Visit(Type theEntityType, MethodCallExpression m, string tableAlias, Stack<string> colConditionParts, List<string> colParameterNames, List<DbType> colDbTypes, List<object> colArguments)
 {
     if (m.Object is MemberExpression)
     {
         //类似n.Name.StartsWith("吴")这样的调用
         if (m.Object.Type == typeof(string))
         {
             StringMethodCallVisitor.Visit(theEntityType, m, tableAlias, colConditionParts, colParameterNames, colDbTypes, colArguments);
         }
         else
         {
             throw new Exception("暂不支持{" + m.ToString() + "}的调用!");
         }
     }
     else if (m.Object is ConstantExpression)
     {
         //类似"ABCD".Contains(n.Name)这样的调用
         var cons = m.Object as ConstantExpression;
         if (cons.Type == typeof(string))
         {
             StringMethodCallVisitor.Visit(theEntityType, m, tableAlias, colConditionParts, colParameterNames, colDbTypes, colArguments);
         }
         else
         {
             throw new Exception("暂不支持{" + m.ToString() + "}的调用!");
         }
     }
     else
     {
        throw new Exception("暂不支持{" + m.ToString() + "}的调用!");
     }
 }
        public Expression Bind(ProjectionExpression projection, ProjectionBindingContext context, MethodCallExpression node, IEnumerable<Expression> arguments)
        {
            var collectionLambda = ExtensionExpressionVisitor.GetLambda(arguments.First());
            var binder = new AccumulatorBinder(context.GroupMap, context.SerializerRegistry);
            binder.RegisterParameterReplacement(collectionLambda.Parameters[0], projection.Projector);

            var collectionSelector = binder.Bind(collectionLambda.Body) as SerializationExpression;
            if (collectionSelector == null)
            {
                var message = string.Format("Unable to determine the collection selector in the tree: {0}", node.ToString());
                throw new NotSupportedException(message);
            }
            var collectionArraySerializer = collectionSelector.SerializationInfo.Serializer as IBsonArraySerializer;
            BsonSerializationInfo collectionItemSerializationInfo;
            if (collectionArraySerializer == null || !collectionArraySerializer.TryGetItemSerializationInfo(out collectionItemSerializationInfo))
            {
                var message = string.Format("The collection selector's serializer must implement IBsonArraySerializer: {0}", node.ToString());
                throw new NotSupportedException(message);
            }

            Expression resultSelector;
            if (arguments.Count() == 2)
            {
                var resultLambda = ExtensionExpressionVisitor.GetLambda(arguments.Last());

                binder.RegisterParameterReplacement(resultLambda.Parameters[0], projection.Projector);
                binder.RegisterParameterReplacement(
                    resultLambda.Parameters[1],
                    new SerializationExpression(
                        resultLambda.Parameters[1],
                        collectionItemSerializationInfo.WithNewName(collectionSelector.SerializationInfo.ElementName)));

                resultSelector = binder.Bind(resultLambda.Body);
            }
            else
            {
                resultSelector = new SerializationExpression(
                    collectionSelector,
                    collectionItemSerializationInfo.WithNewName(collectionSelector.SerializationInfo.ElementName));
            }

            var projector = BuildProjector(resultSelector, context);

            return new ProjectionExpression(
                new SelectManyExpression(
                    projection.Source,
                    collectionSelector,
                    resultSelector),
                projector);
        }
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            Expression retExpr = null;

            if (node.Method.Name == _functionName)
            {
                var str = node.ToString();
                MethodCall call;
                if (_methodCalls.TryGetValue(str, out call))
                {
                    ++call.CallCount;
                }
                else
                {
                    call = new MethodCall(node, Expression.Parameter(node.Type, "param" + (_methodCalls.Count)));
                    _methodCalls.Add(str, call);
                }

                retExpr = call.Parameter;
            }
            else
                retExpr = base.VisitMethodCall(node);

            return retExpr;
        }
Пример #4
0
        protected override Expression VisitMethodCall(MethodCallExpression m)
        {
            string s = m.ToString();
            // VB.net : e.g. CompareString(x.NoCase, "Me 4", False)
            if(s.StartsWith("CompareString"))
            {
                var left = m.Arguments[0];
                // Removes dot if any
                var leftStr = left.ToString().Substring(left.ToString().IndexOf('.') + 1);
                var right = m.Arguments[1].ToString().Replace("\"", String.Empty);
                RDBExpression exp = RDBExpression.Equal;
                _bitmap.Push(qexpression("" + leftStr, exp, right));
                return null;
            }
            string mc = s.Substring(s.IndexOf('.') + 1);
            if (mc.Contains("Between"))
            {
                // TODO : add code for between parsing here

                string name = m.Arguments[0].ToString().Split('.')[1];
                object from = GetValueForMember(m.Arguments[1]);
                object to = GetValueForMember(m.Arguments[2]);
                //var bits = qfromto(name, from, to);
            }
            else
                _stack.Push(mc);

            return m;
        }
            internal override Expression VisitMethodCall(MethodCallExpression m)
            {
                /*
                if ((m.Object != null && ProjectionAnalyzer.IsDisallowedExpressionForMethodCall(m.Object))
                   || m.Arguments.Any(a => ProjectionAnalyzer.IsDisallowedExpressionForMethodCall(a)))
                {
                    throw new NotSupportedException(string.Format(SR.ALinqExpressionNotSupportedInProjection, this.type, m.ToString()));
                }
                */

                if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m))
                {
                    ProjectionAnalyzer.CheckChainedSequence(m, this.type);

                    return base.VisitMethodCall(m);
                }

                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, SR.ALinqExpressionNotSupportedInProjectionToEntity, this.type, m.ToString()));
            }
        /// <summary>
        /// Translate the method call
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="result"></param>
        /// <param name="gc"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public IValue CodeMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, CompositionContainer container)
        {
            Init();

            ///
            /// First see if we can't locate the method call that at least matches in names
            /// 

            var matchingMethodNames = from kt in _knownTypes
                                      where kt.Name == expr.Method.DeclaringType.Name
                                      from m in kt.Methods
                                      where m.Name == expr.Method.Name
                                      select new
                                      {
                                          theType = kt,
                                          theMethod = m
                                      };

            ///
            /// Next, match with the arguments
            /// 

            var matchingMethod = from m in matchingMethodNames
                                 where m.theMethod.Arguments.Length == expr.Arguments.Count
                                 where m.theMethod.Arguments.Zip(expr.Arguments, (us, them) => new Tuple<KnownTypeInfo.MechodArg, Expression>(us, them)).All(apair => apair.Item1.Type == apair.Item2.Type.FullName)
                                 select m;

            ///
            /// Ok, at this point, we should have only one guy. If we have more then just choose the first
            /// 

            var method = matchingMethod.FirstOrDefault();
            if (method == null)
                throw new ArgumentException("Could not find a matching method to translate for the call " + expr.ToString());

            ///
            /// And now translate the call
            /// 

            StringBuilder rawValue = new StringBuilder();

            rawValue.Append(method.theMethod.CPPName);
            rawValue.Append("(");
            bool first = true;
            var dependents = Enumerable.Empty<IDeclaredParameter>();
            foreach (var arg in expr.Arguments.Zip(method.theMethod.Arguments, (m, a) => Tuple.Create(m, a)))
            {
                if (!first)
                    rawValue.Append(",");
                first = false;
                var e = ExpressionToCPP.InternalGetExpression(arg.Item1, gc, null, container);
                rawValue.AppendFormat("({0}){1}", arg.Item2.CPPType, e.RawValue);
                dependents = dependents.Concat(e.Dependants);
            }
            rawValue.Append(")");

            var result = new ValSimple(rawValue.ToString(), expr.Type, dependents);

            ///
            /// Include files
            /// 

            foreach (var ifile in method.theMethod.IncludeFiles)
            {
                gc.AddIncludeFile(ifile);
            }

            ///
            /// We aren't re-writing this expression, so just return it.
            /// 

            return result;
        }
Пример #7
0
        /// <summary>
        /// MethodCallExpression visit method
        /// </summary>
        /// <param name="m">The MethodCallExpression expression to visit</param>
        /// <returns>The visited MethodCallExpression expression </returns>
        internal override Expression VisitMethodCall(MethodCallExpression m)
        {
            string methodName;
            if (TypeSystem.TryGetQueryOptionMethod(m.Method, out methodName))
            {
                this.builder.Append(methodName);
                this.builder.Append(UriHelper.LEFTPAREN);

                // There is a single function, 'contains', which reorders its argument with 
                // respect to the CLR method. Thus handling it as a special case rather than
                // using a more general argument reordering mechanism.
                if (methodName == "contains")
                {
                    Debug.Assert(m.Method.Name == "Contains", "m.Method.Name == 'Contains'");
                    Debug.Assert(m.Object != null, "m.Object != null");
                    Debug.Assert(m.Arguments.Count == 1, "m.Arguments.Count == 1");
                    this.Visit(m.Object);
                    this.builder.Append(UriHelper.COMMA);
                    this.Visit(m.Arguments[0]);
                }
                else
                {
                    if (m.Object != null)
                    {
                        this.Visit(m.Object);
                    }

                    if (m.Arguments.Count > 0)
                    {
                        if (m.Object != null)
                        {
                            this.builder.Append(UriHelper.COMMA);
                        }

                        for (int ii = 0; ii < m.Arguments.Count; ii++)
                        {
                            this.Visit(m.Arguments[ii]);
                            if (ii < m.Arguments.Count - 1)
                            {
                                this.builder.Append(UriHelper.COMMA);
                            }
                        }
                    }
                }

                this.builder.Append(UriHelper.RIGHTPAREN);
            }
            else if (m.Method.Name == "HasFlag")
            {
                Debug.Assert(m.Method.Name == "HasFlag", "m.Method.Name == 'HasFlag'");
                Debug.Assert(m.Object != null, "m.Object != null");
                Debug.Assert(m.Arguments.Count == 1, "m.Arguments.Count == 1");
                this.Visit(m.Object);
                this.builder.Append(UriHelper.SPACE);
                this.builder.Append(UriHelper.HAS);
                this.builder.Append(UriHelper.SPACE);
                this.Visit(m.Arguments[0]);
            }
            else
            {
                SequenceMethod sequenceMethod;
                if (ReflectionUtil.TryIdentifySequenceMethod(m.Method, out sequenceMethod))
                {
                    if (ReflectionUtil.IsAnyAllMethod(sequenceMethod))
                    {
                        // Raise the uriVersion each time we write any or all methods to the uri.
                        WebUtil.RaiseVersion(ref this.uriVersion, Util.ODataVersion4);

                        this.Visit(m.Arguments[0]);
                        this.builder.Append(UriHelper.FORWARDSLASH);
                        if (sequenceMethod == SequenceMethod.All)
                        {
                            this.builder.Append(XmlConstants.AllMethodName);
                        }
                        else
                        {
                            this.builder.Append(XmlConstants.AnyMethodName);
                        }

                        this.builder.Append(UriHelper.LEFTPAREN);
                        if (sequenceMethod != SequenceMethod.Any)
                        {
                            // SequenceMethod.Any represents Enumerable.Any(), which has only source argument
                            // AnyPredicate and All has a second parameter which is the predicate lambda.
                            Debug.Assert(m.Arguments.Count() == 2, "m.Arguments.Count() == 2");
                            LambdaExpression le = (LambdaExpression)m.Arguments[1];
                            string rangeVariable = le.Parameters[0].Name;
                            this.builder.Append(rangeVariable);
                            this.builder.Append(UriHelper.COLON);
                            this.scopeCount++;
                            this.Visit(le.Body);
                            this.scopeCount--;
                        }

                        this.builder.Append(UriHelper.RIGHTPAREN);
                        return m;
                    }
                    else if (sequenceMethod == SequenceMethod.OfType && this.parent != null)
                    {
                        // check to see if this is an OfType filter for Any or All. 
                        // e.g. ctx.CreateQuery<Movie>("Movies").Where(m=>m.Actors.OfType<MegaStar>().Any())
                        //      which translates to /Movies()?$filter=Actors/MegaStar/any()
                        MethodCallExpression mce = this.parent as MethodCallExpression;
                        if (mce != null && ReflectionUtil.TryIdentifySequenceMethod(mce.Method, out sequenceMethod) && ReflectionUtil.IsAnyAllMethod(sequenceMethod))
                        {
                            Type filteredType = mce.Method.GetGenericArguments().SingleOrDefault();
                            if (ClientTypeUtil.TypeOrElementTypeIsEntity(filteredType))
                            {
                                this.Visit(m.Arguments[0]);
                                this.builder.Append(UriHelper.FORWARDSLASH);

                                UriHelper.AppendTypeSegment(this.builder, filteredType, this.context, this.inPath, ref this.uriVersion);

                                return m;
                            }
                        }
                    }
                    else if (sequenceMethod == SequenceMethod.Count && this.parent != null)
                    {
                        if (m.Arguments.Any() && m.Arguments[0] != null)
                        {
                            this.Visit(m.Arguments[0]);
                        }

                        this.builder.Append(UriHelper.FORWARDSLASH).Append(UriHelper.DOLLARSIGN).Append(UriHelper.COUNT);
                        return m;
                    }
                }
                else
                {
                    if (m.Object != null)
                    {
                        this.Visit(m.Object);
                    }

                    if (m.Method.Name != "GetValue" && m.Method.Name != "GetValueAsync")
                    {
                        this.builder.Append(UriHelper.FORWARDSLASH);

                        // writing functions in query options
                        writingFunctionsInQuery = true;
                        string declaringType = this.context.ResolveNameFromTypeInternal(m.Method.DeclaringType);
                        if (string.IsNullOrEmpty(declaringType))
                        {
                            throw new NotSupportedException(Strings.ALinq_CantTranslateExpression(m.ToString()));
                        }

                        int index = declaringType.LastIndexOf('.');
                        string fullNamespace = declaringType.Remove(index + 1);
                        string serverMethodName = ClientTypeUtil.GetServerDefinedName(m.Method);
                        this.builder.Append(fullNamespace + serverMethodName);
                        this.builder.Append(UriHelper.LEFTPAREN);
                        string[] argumentNames = m.Method.GetParameters().Select(p => p.Name).ToArray();
                        for (int i = 0; i < m.Arguments.Count; ++i)
                        {
                            this.builder.Append(argumentNames[i]);
                            this.builder.Append(UriHelper.EQUALSSIGN);
                            this.scopeCount++;
                            this.Visit(m.Arguments[i]);
                            this.scopeCount--;
                            this.builder.Append(UriHelper.COMMA);
                        }

                        if (m.Arguments.Any())
                        {
                            this.builder.Remove(this.builder.Length - 1, 1);
                        }

                        this.builder.Append(UriHelper.RIGHTPAREN);
                        writingFunctionsInQuery = false;
                    }

                    return m;
                }

                this.cantTranslateExpression = true;
            }

            return m;
        }
        /// <summary>
        /// Process a Contains method call which does not map one-to-one on an odata supported method.
        /// </summary>
        /// <param name="expression">
        /// The expression to visit.
        /// </param>
        /// <returns>
        /// The visited expression.
        /// </returns>
        private void VisitContainsMethodCall(MethodCallExpression expression)
        {
            IEnumerable<Expression> arguments = GetFilterMethodArguments(expression, expression.Method.Name, expression.Method.IsGenericMethod);

            //First argument should be a enumerable of constants
            // if you would like to do a enumerable.select().where..
            // you should do that outside of the query for now
            IEnumerable enumerable = null;
            Expression expr = arguments.FirstOrDefault();
            if (expr != null && expr is ConstantExpression)
            {
                enumerable = ((ConstantExpression)expr).Value as IEnumerable;
            }
            Expression comparand = arguments.Skip(1).FirstOrDefault();
            if (enumerable != null && comparand != null)
            {
                List<object> elements = enumerable.OfType<object>().ToList();
                if(elements.Count > 0)
                {
                    // create our rewritten expression tree
                    // by tranforming the contains into a concatenation of 'or' expressions
                    Expression orExpression = elements.Select(o => Expression.Equal(comparand, Expression.Constant(o)))
                    .Aggregate((e1, e2) => Expression.OrElse(e1, e2));
                    
                    this.Visit(orExpression);
                }
            }
            else
            {
                throw new NotSupportedException(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        Resources.FilterBuildingExpressionVisitor_UnsupportedInWhereExpression,
                        expression != null ? expression.ToString() : null));
            }
        }
Пример #9
0
            internal override Expression VisitMethodCall(MethodCallExpression m)
            {
                if ((m.Object != null && IsDisallowedExpressionForMethodCall(m.Object))
                    || m.Arguments.Any(a => IsDisallowedExpressionForMethodCall(a)))
                {
                    throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
                }

                if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m))
                {
                    CheckChainedSequence(m, this.type);

                    // allow selects for following pattern:
                    // Orders = c.Orders.Select(o=> new NarrowOrder {...}).ToList();
                    return base.VisitMethodCall(m);
                }

                throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, m.ToString()));
            }
Пример #10
0
 protected override Expression VisitMethodCall(MethodCallExpression m)
 {
     string s = m.ToString();
     sb.Append(s.Substring(s.IndexOf('.') + 1));
     return m;
 }
Пример #11
0
            internal override Expression VisitMethodCall(MethodCallExpression m)
            {
                if ((m.Object != null && IsDisallowedExpressionForMethodCall(m.Object))
                    || m.Arguments.Any(a => IsDisallowedExpressionForMethodCall(a)))
                {
                    throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
                }

                if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m))
                {
                    CheckChainedSequence(m, this.type);

                    return base.VisitMethodCall(m);
                }

                throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, m.ToString()));
            }
Пример #12
0
        protected override Expression VisitMethodCall(MethodCallExpression e)
        {
            if (e.Method.DeclaringType == typeof(StringQueryExtensions))
                return VisitStringQxMethodCall(e);

            if (e.Method.DeclaringType == typeof(string))
                return VisitStringMethodCall(e);
            
            if (e.Method.DeclaringType == typeof(EnumerableQueryExtensions))
                return VisitEnumerableQxMethodCall(e);

            try
            {
                var value = e.Evaluate();
                var constant = Expression.Constant(value);
                Visit(constant);
            }
            catch (Exception ex)
            {
                throw new NotSupportedException(
                    ExceptionMessages.LambdaParser_UnsupportedMethodCall.Inject(e.ToString()), ex);
            }

            return e;
        }
 /// <summary>
 /// Process method calls which do not map one-to-one on an odata supported method.
 /// Currently we only support Contains.
 /// </summary>
 /// <param name="expression">
 /// The expression to visit.
 /// </param>
 private void VisitCustomMethodCall(MethodCallExpression expression)
 {
     if (expression.Method.Name.Equals("Contains"))
     {
         this.VisitContainsMethodCall(expression);
     }
     else
     {
         throw new NotSupportedException(
             string.Format(
                 CultureInfo.InvariantCulture,
                 "'{0}' is not supported in a 'Where' Mobile Services query expression.",
                 expression != null ? expression.ToString() : null));
     }
 }
Пример #14
0
        protected override Expression VisitMethodCall(MethodCallExpression m)
        {
            string s = m.ToString();
            string mc = s.Substring(s.IndexOf('.') + 1);
            if (mc.Contains("Between"))
            {
                // TODO : add code for between parsing here

                string name = m.Arguments[0].ToString().Split('.')[1];
                object from = GetValueForMember(m.Arguments[1]);
                object to = GetValueForMember(m.Arguments[2]);
                //var bits = qfromto(name, from, to);
            }
            else
                _stack.Push(mc);

            return m;
        }
        private Expression GetAccumulatorArgument(MethodCallExpression node)
        {
            switch (node.Method.Name)
            {
                case "Count":
                case "LongCount":
                    if (node.Arguments.Count == 1)
                    {
                        return Expression.Constant(1);
                    }
                    break;
                case "Average":
                case "Min":
                case "Max":
                case "Sum":
                    if (node.Arguments.Count == 2)
                    {
                        return GetLambda(node.Arguments[1]).Body;
                    }
                    else if (node.Arguments.Count == 1)
                    {
                        return GetBodyFromSelector(node);
                    }
                    break;
                case "First":
                case "Last":
                    // we have already normalized First/Last calls to only have 1 argument...
                    if (node.Arguments.Count == 1)
                    {
                        return GetBodyFromSelector(node);
                    }
                    break;
                case "Select":
                    if (node.Arguments.Count == 2)
                    {
                        return GetLambda(node.Arguments[1]).Body;
                    }
                    break;
                case "Distinct":
                case "ToArray":
                case "ToList":
                    if (node.Arguments.Count == 1)
                    {
                        return GetBodyFromSelector(node);
                    }
                    break;
            }

            var message = string.Format("Unsupported version of accumulator method {0} in the expression tree: {1}.",
                node.Method.Name,
                node.ToString());
            throw new NotSupportedException(message);
        }
            internal override Expression VisitMethodCall(MethodCallExpression m)
            {
                if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m))
                {
                    ProjectionAnalyzer.CheckChainedSequence(m, this.type);

                    return base.VisitMethodCall(m);
                }

                if ((m.Object != null ? CommonUtil.IsClientType(m.Object.Type) : false)
                    || m.Arguments.Any(a => CommonUtil.IsClientType(a.Type)))
                {
                    throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, SR.ALinqExpressionNotSupportedInProjection, this.type, m.ToString()));
                }

                return base.VisitMethodCall(m);
            }
        private BsonValue TranslateMethodCall(MethodCallExpression node)
        {
            BsonValue result;

            if (node.Object == null)
            {
                if (node.Method.DeclaringType == typeof(string)
                    && TryTranslateStaticStringMethodCall(node, out result))
                {
                    return result;
                }

                if (node.Method.DeclaringType == typeof(Math)
                    && TryTranslateStaticMathMethodCall(node, out result))
                {
                    return result;
                }
            }
            else
            {
                if (node.Object.Type == typeof(string)
                    && TryTranslateStringMethodCall(node, out result))
                {
                    return result;
                }

                if (node.Object.Type.IsGenericType
                    && node.Object.Type.GetGenericTypeDefinition() == typeof(HashSet<>)
                    && TryTranslateHashSetMethodCall(node, out result))
                {
                    return result;
                }

                if (node.Method.Name == "CompareTo"
                    && (node.Object.Type.ImplementsInterface(typeof(IComparable<>))
                        || node.Object.Type.ImplementsInterface(typeof(IComparable))))
                {
                    return new BsonDocument("$cmp", new BsonArray(new[] { TranslateValue(node.Object), TranslateValue(node.Arguments[0]) }));
                }

                if (node.Method.Name == "Equals"
                    && node.Arguments.Count == 1)
                {
                    return new BsonDocument("$eq", new BsonArray(new[] { TranslateValue(node.Object), TranslateValue(node.Arguments[0]) }));
                }
            }

            var message = string.Format("{0} of type {1} is not supported in the expression tree {2}.",
                node.Method.Name,
                node.Method.DeclaringType,
                node.ToString());
            throw new NotSupportedException(message);
        }
Пример #18
0
            internal override Expression VisitMethodCall(MethodCallExpression m)
            {
                // We throw NotSupportedException when IsDisallowedExceptionForMethodCall() is true
                // or we have a method call on a non-entity type, for example c.MyCollectionComplexProperty.Select(...)
                if ((m.Object != null && (IsDisallowedExpressionForMethodCall(m.Object, this.context.Model) || !ClientTypeUtil.TypeOrElementTypeIsEntity(m.Object.Type)))
                    || m.Arguments.Any(a => IsDisallowedExpressionForMethodCall(a, this.context.Model))
                    || (m.Object == null && !ClientTypeUtil.TypeOrElementTypeIsEntity(m.Arguments[0].Type)))
                {
                    throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
                }

                if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m))
                {
                    CheckChainedSequence(m, this.type);

                    // allow selects for following pattern:
                    // Orders = c.Orders.Select(o=> new NarrowOrder {...}).ToList();
                    return base.VisitMethodCall(m);
                }

                throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, m.ToString()));
            }
Пример #19
0
 /// <summary>
 /// Checks whether the specified <see cref="MethodCallExpression"/> refers
 /// to a Select method call that works on the results of another Select call
 /// </summary>
 /// <param name="call">Method call expression to check.</param>
 /// <param name="type">Type of the projection</param>
 internal static void CheckChainedSequence(MethodCallExpression call, Type type)
 {
     if (ReflectionUtil.IsSequenceMethod(call.Method, SequenceMethod.Select))
     {
         // Chained Selects are not allowed
         // c.Orders.Select(...).Select(...)
         MethodCallExpression insideCall = ResourceBinder.StripTo<MethodCallExpression>(call.Arguments[0]);
         if (insideCall != null && ReflectionUtil.IsSequenceMethod(insideCall.Method, SequenceMethod.Select))
         {
             throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(type, call.ToString()));
         }
     }
 }
Пример #20
0
 internal override Expression VisitMethodCall(MethodCallExpression m)
 {
     if (((m.Object != null) && ProjectionAnalyzer.IsDisallowedExpressionForMethodCall(m.Object, this.context.MaxProtocolVersion)) || m.Arguments.Any<Expression>(a => ProjectionAnalyzer.IsDisallowedExpressionForMethodCall(a, this.context.MaxProtocolVersion)))
     {
         throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
     }
     ProjectionAnalyzer.CheckChainedSequence(m, this.type);
     if (!ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m) && (((m.Object != null) ? ClientTypeUtil.TypeOrElementTypeIsEntity(m.Object.Type) : false) || m.Arguments.Any<Expression>(a => ClientTypeUtil.TypeOrElementTypeIsEntity(a.Type))))
     {
         throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
     }
     return base.VisitMethodCall(m);
 }
Пример #21
0
            internal override Expression VisitMethodCall(MethodCallExpression m)
            {
                if ((m.Object != null && IsDisallowedExpressionForMethodCall(m.Object))
                    || m.Arguments.Any(a => IsDisallowedExpressionForMethodCall(a)))
                {
                    throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
                }

                if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m))
                {
                    CheckChainedSequence(m, this.type);

                    // allow IEnum.Select and IEnum.ToList even if entity type.
                    return base.VisitMethodCall(m);
                }

                if ((m.Object != null ? ClientType.CheckElementTypeIsEntity(m.Object.Type) : false) 
                    || m.Arguments.Any(a => ClientType.CheckElementTypeIsEntity(a.Type)))
                {
                    throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
                }

                return base.VisitMethodCall(m);
            }
Пример #22
0
 internal static void CheckChainedSequence(MethodCallExpression call, Type type)
 {
     if (ReflectionUtil.IsSequenceSelectMethod(call.Method))
     {
         MethodCallExpression expression = ResourceBinder.StripTo<MethodCallExpression>(call.Arguments[0]);
         if ((expression != null) && ReflectionUtil.IsSequenceSelectMethod(expression.Method))
         {
             throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(type, call.ToString()));
         }
     }
 }
 /// <summary>
 /// Process method calls which do not map one-to-one on an odata supported method.
 /// Currently we only support Contains.
 /// </summary>
 /// <param name="expression">
 /// The expression to visit.
 /// </param>
 private void VisitCustomMethodCall(MethodCallExpression expression)
 {
     if (expression.Method.Name.Equals("Contains"))
     {
         this.VisitContainsMethodCall(expression);
     }
     else
     {
         throw new NotSupportedException(
             string.Format(
                 CultureInfo.InvariantCulture,
                 Resources.FilterBuildingExpressionVisitor_UnsupportedInWhereExpression,
                 expression != null ? expression.ToString() : null));
     }
 }
Пример #24
0
 /// <summary>
 /// 访问指定的方法
 /// </summary>
 /// <param name="theEntityType">实体的类型</param>
 /// <param name="m">访问方法调用相关的表达式</param>
 /// <param name="tableAlias">表的别名</param>
 /// <param name="colConditionParts">存储条件节点的栈</param>
 /// <param name="colParameterNames">存储参数名称的列表</param>
 /// <param name="colDbTypes">存储数据库字段类型的列表</param>
 /// <param name="colArguments">存储条件值的列表</param>
 public static void Visit(Type theEntityType, MethodCallExpression m, string tableAlias,
     Stack<string> colConditionParts, List<string> colParameterNames, List<DbType> colDbTypes,
     List<object> colArguments)
 {
     string methodName = m.Method.Name;
     if (m.Object is MemberExpression)
     {
         string condition = null;
         //string memberName = GetMemberName(m.Object as MemberExpression, out theDbType);
         string memberName = EntityMappingTool.GetDbColumnName(theEntityType,
             ((MemberExpression) m.Object).Member.Name);
         DbType theDbType = EntityMappingTool.GetDbColumnType(theEntityType,
             ((MemberExpression) m.Object).Member.Name);
         string parameterName = GetParameterName(colParameterNames, memberName, tableAlias);
         switch (methodName)
         {
             case "Contains":
                 condition = string.Format("({0}.[{1}] like {2})", tableAlias, memberName, parameterName);
                 colConditionParts.Push(condition);
                 colParameterNames.Add(parameterName);
                 colDbTypes.Add(theDbType);
                 colArguments.Add("%" + GetArgumentValue(m.Arguments[0] as ConstantExpression) + "%");
                 break;
             case "StartsWith":
                 condition = string.Format("({0}.[{1}] like {2})", tableAlias, memberName, parameterName);
                 colConditionParts.Push(condition);
                 colParameterNames.Add(parameterName);
                 colDbTypes.Add(theDbType);
                 colArguments.Add(GetArgumentValue(m.Arguments[0] as ConstantExpression) + "%");
                 break;
             case "EndsWith":
                 condition = string.Format("({0}.[{1}] like {2})", tableAlias, memberName, parameterName);
                 colConditionParts.Push(condition);
                 colParameterNames.Add(parameterName);
                 colDbTypes.Add(theDbType);
                 colArguments.Add("%" + GetArgumentValue(m.Arguments[0] as ConstantExpression));
                 break;
             default:
                 throw new EntitySqlException("暂不支持{" + m.ToString() + "}的调用!");
         }
     }
     else if (m.Object is ConstantExpression)
     {
         string condition = null;
         string memberName = EntityMappingTool.GetDbColumnName(theEntityType,
             ((MemberExpression) m.Arguments[0]).Member.Name);
         DbType theDbType = EntityMappingTool.GetDbColumnType(theEntityType,
             ((MemberExpression) m.Arguments[0]).Member.Name);
         string parameterName = GetParameterName(colParameterNames, memberName, tableAlias);
         switch (methodName)
         {
             case "Contains":
                 condition = string.Format("(CHARINDEX({0},{1}.[{2}])>0)", parameterName, tableAlias, memberName);
                 colConditionParts.Push(condition);
                 colParameterNames.Add(parameterName);
                 colDbTypes.Add(theDbType);
                 colArguments.Add(GetArgumentValue(m.Object as ConstantExpression));
                 break;
             case "StartsWith":
                 condition = string.Format("(CHARINDEX({0},{1}.[{2}])=1)", parameterName, tableAlias, memberName);
                 colConditionParts.Push(condition);
                 colParameterNames.Add(parameterName);
                 colDbTypes.Add(theDbType);
                 colArguments.Add(GetArgumentValue(m.Object as ConstantExpression));
                 break;
             default:
                 throw new EntitySqlException("暂不支持{" + m.ToString() + "}的调用!");
         }
     }
     else
     {
         throw new EntitySqlException("暂不支持{" + m.ToString() + "}的调用!");
     }
 }
Пример #25
0
        private string TranslateMethodCall(MethodCallExpression node)
        {
            var methodName = node.Method.Name;
            MemberExpression leftExpression = null;
            var arguments = new List<LambdaExpression>();

            if (node.Method.DeclaringType == typeof(string))
            {
                string arg = Translate(node.Object);

                object[] stringArguments = node.Arguments.Select(UnQuote).OfType<ConstantExpression>().Select(exp => exp.Value).ToArray();

                switch (methodName)
                {
                    case "StartsWith":
                        return string.Format("({0} like {1})", arg, CreateParameter(stringArguments[0] + "%"));
                    case "EndsWith":
                        return string.Format("({0} like {1})", arg, CreateParameter("%" + stringArguments[0]));
                    case "Contains":
                        return string.Format("({0} like {1})", arg, CreateParameter("%" + stringArguments[0] + "%"));
                    case "Trim":
                        return string.Format(_sqlDialect.SqlFunction(SqlDialect.Function.Trim), stringArguments[0]);
                }

                throw new SqlExpressionTranslatorException(node.ToString());
            }

            if (node.Method.DeclaringType.IsConstructedGenericType && node.Method.DeclaringType.GetGenericTypeDefinition() == typeof(IDataSet<>))
            {
                leftExpression = node.Object as MemberExpression;
                arguments.AddRange(node.Arguments.Select(UnQuote).OfType<LambdaExpression>());
            }

            if (node.Method.DeclaringType == typeof(Enumerable) && node.Arguments.Count > 0)
            {
                leftExpression = node.Arguments[0] as MemberExpression;
                arguments.AddRange(node.Arguments.Skip(1).Select(UnQuote).OfType<LambdaExpression>());
            }

            if (leftExpression != null)
            {
                switch (methodName)
                {
                    case "Any":
                    case "Count":
                    case "All":
                        return TranslateOneToMany(
                            methodName,
                            leftExpression,
                            null,
                            arguments.Count > 0 ? arguments[0] : null
                            );
                    case "Sum":
                    case "Avg":
                        return TranslateOneToMany(
                            methodName,
                            leftExpression,
                            arguments[0],
                            null
                            );
                }
            }

            throw new SqlExpressionTranslatorException(node.ToString());
        }
 internal static void CheckChainedSequence(MethodCallExpression call, Type type)
 {
     if (ReflectionUtil.IsSequenceMethod(call.Method, SequenceMethod.Select))
     {
         MethodCallExpression insideCall = ResourceBinder.StripTo<MethodCallExpression>(call.Arguments[0]);
         if (insideCall != null && ReflectionUtil.IsSequenceMethod(insideCall.Method, SequenceMethod.Select))
         {
             throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, SR.ALinqExpressionNotSupportedInProjection, type, call.ToString()));
         }
     }
 }
 protected override Expression VisitOtherMethodCall(MethodCallExpression expression)
 {
     throw new NotSupportedException(String.Format("Method Call to {0} is not supported.", expression.ToString()));
 }
        private Expression BuildFromMethodCall(MethodCallExpression node)
        {
            Expression source;
            IEnumerable<Expression> arguments;

            if (node.Object != null)
            {
                source = node.Object;
                arguments = node.Arguments;
            }
            else
            {
                // assuming an extension method here...
                source = node.Arguments[0];
                arguments = node.Arguments.Skip(1);
            }

            var projection = BindProjection(source);
            var result = _methodCallBinder.Bind(projection, _context, node, arguments);
            if (result == null)
            {
                var message = string.Format("The method {0} is not supported in the expression tree: {1}.",
                    node.Method.Name,
                    node.ToString());
                throw new NotSupportedException(message);
            }

            return result;
        }