コード例 #1
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            Expression rewrite = null;
            if (TryUncheckedCast(node,ref rewrite))
                return rewrite;

            return base.VisitMethodCall(node);
        }
コード例 #2
0
        private static string GetTypeOfNthParamOfMethod(int ParamIndex, MethodCallExpression MethodCallExpression)
        {
            MethodReferenceExpression OuterMethodReference = (MethodCallExpression.Nodes[0] as DevExpress.CodeRush.StructuralParser.MethodReferenceExpression);

            var Declaration1 = OuterMethodReference.GetDeclaration() as Method;
            // Previous line will return null if any parameter isn't explicitly calculable.
            if (Declaration1 == null)
                return ""; // Suggest void. Wrong, but best available option.

            var Param = Declaration1.Parameters[ParamIndex] as Param;
            return Param.GetTypeName();
        }
コード例 #3
0
        /// <summary>
        /// Given a MethodCallExpression, copy the expression, replacing the source with the source provided
        /// </summary>
        /// <param name="source"></param>
        /// <param name="mce"></param>
        /// <returns></returns>
        private static System.Linq.Expressions.MethodCallExpression ResourceQueryOperatorCall(System.Linq.Expressions.Expression source, MethodCallExpression mce)
        {
            List <System.Linq.Expressions.Expression> exprs = new List <System.Linq.Expressions.Expression>();

            exprs.Add(source);
            exprs.AddRange(mce.Arguments.Skip(1));
            return(System.Linq.Expressions.Expression.Call(mce.Method, exprs.ToArray()));
        }
コード例 #4
0
 protected override Expression VisitMethodCall(MethodCallExpression m)
 {
     Accumulate(m.Method);
     return base.VisitMethodCall(m);
 }
コード例 #5
0
ファイル: ExpressionDumper.cs プロジェクト: jmclain/Nmp
		/////////////////////////////////////////////////////////////////////////////

		public override string DumpMethodCallExpression( MethodCallExpression exp )
		{
			return string.Format( ".{0}({1})", exp.MethodName, Arguments(exp.Arguments) );
		}
コード例 #6
0
ファイル: ExpressionWriter.cs プロジェクト: tapika/swupd
        /// <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, 'substringof', 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 == "substringof")
                {
                    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.Arguments[0]);
                    this.builder.Append(UriHelper.COMMA);
                    this.Visit(m.Object);
                }
                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
            {
                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.DataServiceVersion3);

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

                this.cantTranslateExpression = true;
            }

            return(m);
        }
コード例 #7
0
ファイル: CallFactoryTests.cs プロジェクト: dotnet/corefx
        private static void AssertCallIsOptimized(MethodCallExpression expr, Expression instance, MethodInfo method, IReadOnlyList<Expression> args)
        {
            int n = method.GetParameters().Length;

            MethodCallExpression updatedArgs = UpdateArgs(expr);
            MethodCallExpression visitedArgs = VisitArgs(expr);
            var updatedObj = default(MethodCallExpression);
            var visitedObj = default(MethodCallExpression);

            MethodCallExpression[] nodes;

            if (instance == null)
            {
                nodes = new[] { expr, updatedArgs, visitedArgs };
            }
            else
            {
                updatedObj = UpdateObj(expr);
                visitedObj = VisitObj(expr);

                nodes = new[] { expr, updatedArgs, visitedArgs, updatedObj, visitedObj };
            }

            foreach (var node in nodes)
            {
                if (node != visitedObj && node != updatedObj)
                {
                    Assert.Same(instance, node.Object);
                }

                Assert.Same(method, node.Method);

                if (method.IsStatic)
                {
                    AssertStaticMethodCall(n, node);
                }
                else
                {
                    AssertInstanceMethodCall(n, node);
                }

                var argProvider = node as IArgumentProvider;
                Assert.NotNull(argProvider);

                Assert.Equal(n, argProvider.ArgumentCount);

                Assert.Throws<ArgumentOutOfRangeException>(() => argProvider.GetArgument(-1));
                Assert.Throws<ArgumentOutOfRangeException>(() => argProvider.GetArgument(n));

                if (node != visitedArgs) // our visitor clones argument nodes
                {
                    for (var i = 0; i < n; i++)
                    {
                        Assert.Same(args[i], argProvider.GetArgument(i));
                        Assert.Same(args[i], node.Arguments[i]);
                    }
                }
            }
        }
コード例 #8
0
 // MethodCallExpression
 protected internal virtual bool Walk(MethodCallExpression node) { return true; }
コード例 #9
0
 protected virtual bool CompareMethodCall(MethodCallExpression a, MethodCallExpression b)
 {
     return a.Method == b.Method
         && this.Compare(a.Object, b.Object)
         && this.CompareExpressionList(a.Arguments, b.Arguments);
 }
コード例 #10
0
 /// <summary>
 ///     Returns the operator to emit (e.g. LIKE/ILIKE).
 /// </summary>
 /// <param name="expression"></param>
 /// <returns></returns>
 protected virtual string GetOperator(MethodCallExpression expression)
 {
     return(IsCaseInsensitiveComparison(expression) ? "ILIKE" : "LIKE");
 }
コード例 #11
0
 public static ITranslation GetSubjectTranslation(MethodCallExpression methodCall, ITranslationContext context)
 {
     return(context.GetTranslationFor(methodCall.GetSubject()) ??
            context.GetTranslationFor(methodCall.Method.DeclaringType));
 }
コード例 #12
0
ファイル: ExpressionTest.cs プロジェクト: ewin66/CSharp-Study
        public static void Show()
        {
            {
                Func <int, int, int> func = (m, n) => m * n + 2;
                Expression <Func <int, int, int> > exp = (m, n) => m * n + 2;//lambda表达式声明表达式目录树
                //Expression<Func<int, int, int>> exp1 = (m, n) =>
                //    {
                //        return m * n + 2;
                //    };


                //表达式目录树:语法树,或者说是一种数据结构
                int iResult1 = func.Invoke(12, 23);
                int iResult2 = exp.Compile().Invoke(12, 23);
            }
            {
                //自己拼装表达式目录树
                ParameterExpression parameterExpression  = Expression.Parameter(typeof(int), "m");                         //m
                ParameterExpression parameterExpression2 = Expression.Parameter(typeof(int), "n");                         //n
                BinaryExpression    binaryExpression     = Expression.Multiply(parameterExpression, parameterExpression2); //m*n
                ConstantExpression  constantExpression   = Expression.Constant(2, typeof(int));                            //2
                BinaryExpression    binaryExpressionAdd  = Expression.Add(binaryExpression, constantExpression);           //M*N+2
                Expression <Func <int, int, int> > exp   = Expression.Lambda <Func <int, int, int> >(binaryExpressionAdd, new ParameterExpression[]
                {
                    parameterExpression,
                    parameterExpression2
                });

                int iResult2 = exp.Compile().Invoke(12, 23);
            }
            {
                ParameterExpression paraLeft   = Expression.Parameter(typeof(int), "a");   //左边
                ParameterExpression paraRight  = Expression.Parameter(typeof(int), "b");   //右边
                BinaryExpression    binaryLeft = Expression.Multiply(paraLeft, paraRight); //a*b
                ConstantExpression  conRight   = Expression.Constant(2, typeof(int));      //右边常量
                BinaryExpression    binaryBody = Expression.Add(binaryLeft, conRight);     //a*b+2

                //只能执行表示Lambda表达式的表达式目录树,即LambdaExpression或者Expression<TDelegate>类型。如果表达式目录树不是表示Lambda表达式,需要调用Lambda方法创建一个新的表达式
                Expression <Func <int, int, int> > lambda =
                    Expression.Lambda <Func <int, int, int> >(binaryBody, paraLeft, paraRight);
                Func <int, int, int> func = lambda.Compile();//Expression Compile成委托
                int result = func(3, 4);
            }
            {
                //常量
                ConstantExpression  conLeft       = Expression.Constant(345);
                ConstantExpression  conRight      = Expression.Constant(456);
                BinaryExpression    binary        = Expression.Add(conLeft, conRight); //添加方法的
                Expression <Action> actExpression = Expression.Lambda <Action>(binary, null);
                actExpression.Compile()();                                             //()=>345+456
            }

            {
                string sql = "SELECT * FROM uSER WHERE 1=1";
                if (true)
                {
                    sql += " and ";
                }
                if (true)
                {
                    sql += " and ";
                }

                IQueryable <int> list = null;



                //if (true) list = list.Where(i => i > 5);
                //if (true) list = list.Where(i => i > 5);

                if (true)
                {
                    Expression <Func <int, bool> > exp1 = x => x > 1;
                }
                if (true)
                {
                    Expression <Func <int, bool> > exp2 = x => x > 2;
                }
                Expression <Func <int, bool> > exp3 = x => x > 1 && x > 2;


                //list.Where()

                //拼装表达式目录树,交给下端用
                //Expression<Func<People, bool>> lambda = x => x.Age > 5;
                ParameterExpression parameterExpression = Expression.Parameter(typeof(People), "x");
                //Expression property = Expression.Property(parameterExpression, typeof(People).GetProperty("Age"));
                Expression         property              = Expression.Field(parameterExpression, typeof(People).GetField("Id"));
                ConstantExpression constantExpression    = Expression.Constant(5, typeof(int));
                BinaryExpression   binary                = Expression.GreaterThan(property, constantExpression);//添加方法的
                Expression <Func <People, bool> > lambda = Expression.Lambda <Func <People, bool> >(binary, new ParameterExpression[]
                {
                    parameterExpression
                });
                bool bResult = lambda.Compile()(new People()
                {
                    Id   = 11,
                    Name = "打兔子的猎人",
                    Age  = 28
                });
            }
            {
                //Expression<Func<People, bool>> lambda = x => x.Id.ToString().Equals("5");
                ParameterExpression  parameterExpression = Expression.Parameter(typeof(People), "x");
                Expression           field              = Expression.Field(parameterExpression, typeof(People).GetField("Id"));
                MethodCallExpression toString           = Expression.Call(field, typeof(People).GetMethod("ToString"), new Expression[0]);
                ConstantExpression   constantExpression = Expression.Constant("5", typeof(string));

                MethodCallExpression equals = Expression.Call(toString, typeof(People).GetMethod("Equals"), new Expression[] { constantExpression });
                Expression <Func <People, bool> > lambda = Expression.Lambda <Func <People, bool> >(equals, new ParameterExpression[]
                {
                    parameterExpression
                });
                bool bResult = lambda.Compile()(new People()
                {
                    Id   = 11,
                    Name = "打兔子的猎人",
                    Age  = 28
                });
            }
            {
                People people = new People()
                {
                    Id   = 11,
                    Name = "打兔子的猎人",
                    Age  = 28
                };
                PeopleCopy peopleCopy = new PeopleCopy()
                {
                    Id   = people.Id,
                    Name = people.Name,
                    Age  = people.Age
                };
                PeopleCopy peopleCopy1 = Trans <People, PeopleCopy>(people);


                //Expression<Func<People, PeopleCopy>> lambda = p =>
                //        new PeopleCopy()
                //        {
                //            Id = p.Id,
                //            Name = p.Name,
                //            Age = p.Age
                //        };
                //lambda.Compile()(people);

                ParameterExpression  parameterExpression = Expression.Parameter(typeof(People), "p");
                List <MemberBinding> memberBindingList   = new List <MemberBinding>();
                foreach (var item in typeof(PeopleCopy).GetProperties())
                {
                    MemberExpression property      = Expression.Property(parameterExpression, typeof(People).GetProperty(item.Name));
                    MemberBinding    memberBinding = Expression.Bind(item, property);
                    memberBindingList.Add(memberBinding);
                }
                foreach (var item in typeof(PeopleCopy).GetFields())
                {
                    MemberExpression property      = Expression.Field(parameterExpression, typeof(People).GetField(item.Name));
                    MemberBinding    memberBinding = Expression.Bind(item, property);
                    memberBindingList.Add(memberBinding);
                }
                MemberInitExpression memberInitExpression      = Expression.MemberInit(Expression.New(typeof(PeopleCopy)), memberBindingList.ToArray());
                Expression <Func <People, PeopleCopy> > lambda = Expression.Lambda <Func <People, PeopleCopy> >(memberInitExpression, new ParameterExpression[]
                {
                    parameterExpression
                });
                Func <People, PeopleCopy> func = lambda.Compile();//拼装是一次性的

                TransExp <People, PeopleCopy>(people);
                TransExp <People, PeopleCopy>(people);
                TransExp <People, PeopleCopy>(people);
                TransExp <People, PeopleCopy>(people);
                TransExp <People, PeopleCopy>(people);
                TransExp <People, PeopleCopy>(people);
                TransExp <People, PeopleCopy>(people);
                TransExp <People, PeopleCopy>(new People()
                {
                    Id   = 12,
                    Name = "小雨天",
                    Age  = 26
                });
            }

            #region 表达式链接
            {
                Expression <Func <People, bool> > lambda1 = x => x.Age > 5;
                Expression <Func <People, bool> > lambda2 = x => x.Id > 5;
                Expression <Func <People, bool> > lambda3 = lambda1.And(lambda2);
                Expression <Func <People, bool> > lambda4 = lambda1.Or(lambda2);
                Expression <Func <People, bool> > lambda5 = lambda1.Not();
                Do1(lambda3);
                Do1(lambda4);
                Do1(lambda5);
            }
            #endregion
        }
コード例 #13
0
 private static bool IsStringConcatCall(MethodCallExpression methodCall)
 {
     return(methodCall.Method.IsStatic &&
            (methodCall.Method.DeclaringType == typeof(string)) &&
            (methodCall.Method.Name == "Concat"));
 }
コード例 #14
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequenceExpr             = methodCall.Arguments[0];
            var wrapSequence             = false;
            LambdaExpression?groupingKey = null;
            var groupingKind             = GroupingType.Default;

            if (sequenceExpr.NodeType == ExpressionType.Call)
            {
                var call = (MethodCallExpression)methodCall.Arguments[0];

                if (call.IsQueryable("Select"))
                {
                    var selectParam = (LambdaExpression)call.Arguments[1].Unwrap();
                    var type        = selectParam.Body.Type;

                    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ExpressionBuilder.GroupSubQuery <,>))
                    {
                        wrapSequence = true;

                        var selectParamBody = selectParam.Body.Unwrap();
                        MethodCallExpression?groupingMethod = null;
                        if (selectParamBody is MemberInitExpression mi)
                        {
                            var assignment = mi.Bindings.OfType <MemberAssignment>().FirstOrDefault(m => m.Member.Name == "Key");
                            if (assignment?.Expression.NodeType == ExpressionType.Call)
                            {
                                var mc = (MethodCallExpression)assignment.Expression;
                                if (mc.IsSameGenericMethod(GroupingSetMethods))
                                {
                                    groupingMethod = mc;
                                    groupingKey    = (LambdaExpression)mc.Arguments[0].Unwrap();
                                    if (mc.IsSameGenericMethod(Methods.LinqToDB.GroupBy.Rollup))
                                    {
                                        groupingKind = GroupingType.Rollup;
                                    }
                                    else if (mc.IsSameGenericMethod(Methods.LinqToDB.GroupBy.Cube))
                                    {
                                        groupingKind = GroupingType.Cube;
                                    }
                                    else if (mc.IsSameGenericMethod(Methods.LinqToDB.GroupBy.GroupingSets))
                                    {
                                        groupingKind = GroupingType.GroupBySets;
                                    }
                                    else
                                    {
                                        throw new InvalidOperationException();
                                    }
                                }
                            }
                        }

                        if (groupingMethod != null && groupingKey != null)
                        {
                            sequenceExpr = sequenceExpr.Replace(groupingMethod, groupingKey.Body.Unwrap());
                        }
                    }
                }
            }

            var sequence    = builder.BuildSequence(new BuildInfo(buildInfo, sequenceExpr));
            var keySequence = sequence;

            var groupingType    = methodCall.Type.GetGenericArguments()[0];
            var keySelector     = (LambdaExpression)methodCall.Arguments[1].Unwrap() !;
            var elementSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap() !;

            if (wrapSequence)
            {
                sequence = new SubQueryContext(sequence);
            }

            sequence = new SubQueryContext(sequence);
            var key = new KeyContext(buildInfo.Parent, keySelector, sequence);

            if (groupingKind != GroupingType.GroupBySets)
            {
                var groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key, null);

                var allowed = groupSql.Where(s => !QueryHelper.IsConstantFast(s.Sql));

                foreach (var sql in allowed)
                {
                    sequence.SelectQuery.GroupBy.Expr(sql.Sql);
                }
            }
            else
            {
                var goupingSetBody = groupingKey !.Body;
                var groupingSets   = EnumGroupingSets(goupingSetBody).ToArray();
                if (groupingSets.Length == 0)
                {
                    throw new LinqException($"Invalid grouping sets expression '{goupingSetBody}'.");
                }

                foreach (var groupingSet in groupingSets)
                {
                    var groupSql = builder.ConvertExpressions(keySequence, groupingSet, ConvertFlags.Key, null);
                    sequence.SelectQuery.GroupBy.Items.Add(
                        new SqlGroupingSet(groupSql.Select(s => keySequence.SelectQuery.Select.AddColumn(s.Sql))));
                }
            }

            sequence.SelectQuery.GroupBy.GroupingType = groupingKind;

            var element = new SelectContext(buildInfo.Parent, elementSelector, sequence /*, key*/);
            var groupBy = new GroupByContext(buildInfo.Parent, sequenceExpr, groupingType, sequence, key, element, builder.IsGroupingGuardDisabled);

            Debug.WriteLine("BuildMethodCall GroupBy:\n" + groupBy.SelectQuery);

            return(groupBy);
        }
コード例 #15
0
        /// <summary>
        ///     Returns a locator for the member being queried upon
        /// </summary>
        /// <param name="mapping"></param>
        /// <param name="expression"></param>
        /// <returns></returns>
        protected string GetLocator(IFieldMapping mapping, MethodCallExpression expression)
        {
            var memberExpression = determineStringField(expression);

            return(mapping.FieldFor(memberExpression).RawLocator);
        }
コード例 #16
0
 protected MethodCallExpression UpdateMethodCall(MethodCallExpression m, Expression obj, MethodInfo method, IEnumerable<Expression> args)
 {
     if (obj != m.Object || method != m.Method || args != m.Arguments)
     {
         return Expression.Call(obj, method, args);
     }
     return m;
 }
コード例 #17
0
ファイル: ETB.cs プロジェクト: jmclain/Nmp
		/////////////////////////////////////////////////////////////////////////////

		protected Expression MethodCall( bool isRootNode, string methodName, bool validToken, IInput input )
		{
			// ******
			Expression expression = null;

			IArgumentsProcessor ap = new ArgumentsProcessor( scanner, recognizer );

			NmpStringList strArgs = scanner.ArgScanner( input, RecognizedCharType.CloseParenChar );

			// ******
			if( ! validToken ) {
				//
				// IndexResult
				//
				return new UnnamedMethodCallExpression( ap, strArgs );
			}
			else {
				if( isRootNode ) {
					expression = new UnnamedMethodCallExpression( methodName, ap, strArgs );
				}
				else {
					expression = new MethodCallExpression( methodName, ap, strArgs );
				}
			}

			// ******
			return expression;
		}
コード例 #18
0
 protected override Expression VisitMethodCall(MethodCallExpression node)
 {
     return(Visiting((expr) => base.VisitMethodCall(expr as MethodCallExpression), node));
 }
コード例 #19
0
ファイル: ExpressionDumper.cs プロジェクト: jmclain/Nmp
		public abstract string DumpMethodCallExpression( MethodCallExpression exp );
コード例 #20
0
        internal static IProjection ProcessDoubleAbs(MethodCallExpression methodCallExpression)
        {
            IProjection property = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]).AsProjection();

            return(Projections.SqlFunction("abs", NHibernateUtil.Double, property));
        }
コード例 #21
0
        internal static IProjection ProcessBitLength(MethodCallExpression methodCallExpression)
        {
            IProjection property = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]).AsProjection();

            return(Projections.SqlFunction("bit_length", NHibernateUtil.String, property));
        }
コード例 #22
0
 public MethodCallExpressionProxy(MethodCallExpression node) {
     _node = node;
 }
コード例 #23
0
 private bool CompareMethodCall(MethodCallExpression a, MethodCallExpression b)
 => Equals(a.Method, b.Method) &&
 Compare(a.Object, b.Object) &&
 CompareExpressionList(a.Arguments, b.Arguments);
コード例 #24
0
ファイル: CallFactoryTests.cs プロジェクト: dotnet/corefx
        private static MethodCallExpression UpdateObj(MethodCallExpression node)
        {
            // Tests the call of Update to Expression.Call factories.

            MethodCallExpression res = node.Update(new VisitorObj().Visit(node.Object), node.Arguments);

            Assert.NotSame(node, res);

            return res;
        }
コード例 #25
0
        public override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc)
        {
            Func <Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);

            if (exp.Object == null)
            {
                switch (exp.Method.Name)
                {
                case "IsNullOrEmpty":
                    var arg1 = getExp(exp.Arguments[0]);
                    return($"({arg1} is null or {arg1} = '')");

                case "IsNullOrWhiteSpace":
                    var arg2 = getExp(exp.Arguments[0]);
                    return($"({arg2} is null or {arg2} = '' or ltrim({arg2}) = '')");

                case "Concat":
                    return(_common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), null));

                case "Format":
                    if (exp.Arguments[0].NodeType != ExpressionType.Constant)
                    {
                        throw new Exception(CoreStrings.Not_Implemented_Expression_ParameterUseConstant(exp, exp.Arguments[0]));
                    }
                    var expArgsHack = exp.Arguments.Count == 2 && exp.Arguments[1].NodeType == ExpressionType.NewArrayInit ?
                                      (exp.Arguments[1] as NewArrayExpression).Expressions : exp.Arguments.Where((a, z) => z > 0);
                    //3个 {} 时,Arguments 解析出来是分开的
                    //4个 {} 时,Arguments[1] 只能解析这个出来,然后里面是 NewArray []
                    var expArgs = expArgsHack.Select(a => $"'||{_common.IsNull(ExpressionLambdaToSql(a, tsc), "''")}||'").ToArray();
                    return(string.Format(ExpressionLambdaToSql(exp.Arguments[0], tsc), expArgs));

                case "Join":     //未通用测试 #405
                    if (exp.IsStringJoin(out var tolistObjectExp, out var toListMethod, out var toListArgs1))
                    {
                        var newToListArgs0 = Expression.Call(tolistObjectExp, toListMethod,
                                                             Expression.Lambda(
                                                                 Expression.Call(
                                                                     typeof(SqlExtExtensions).GetMethod("StringJoinOracleGroupConcat"),
                                                                     Expression.Convert(toListArgs1.Body, typeof(object)),
                                                                     Expression.Convert(exp.Arguments[0], typeof(object))),
                                                                 toListArgs1.Parameters));
                        var newToListSql = getExp(newToListArgs0);
                        return(newToListSql);
                    }
                    break;
                }
            }
            else
            {
                var left = getExp(exp.Object);
                switch (exp.Method.Name)
                {
                case "StartsWith":
                case "EndsWith":
                case "Contains":
                    var args0Value = getExp(exp.Arguments[0]);
                    if (args0Value == "NULL")
                    {
                        return($"({left}) IS NULL");
                    }
                    var likeOpt = "LIKE";
                    if (exp.Arguments.Count > 1)
                    {
                        if (exp.Arguments[1].Type == typeof(bool) ||
                            exp.Arguments[1].Type == typeof(StringComparison))
                        {
                            likeOpt = "ILIKE";
                        }
                    }
                    if (exp.Method.Name == "StartsWith")
                    {
                        return($"({left}) {likeOpt} {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(({args0Value})::text || '%')")}");
                    }
                    if (exp.Method.Name == "EndsWith")
                    {
                        return($"({left}) {likeOpt} {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%' || ({args0Value})::text)")}");
                    }
                    if (args0Value.StartsWith("'") && args0Value.EndsWith("'"))
                    {
                        return($"({left}) {likeOpt} {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}");
                    }
                    return($"({left}) {likeOpt} ('%' || ({args0Value})::text || '%')");
コード例 #26
0
        private void AddressOf(MethodCallExpression node, Type type)
        {
            // An array index of a multi-dimensional array is represented by a call to Array.Get,
            // rather than having its own array-access node. This means that when we are trying to
            // get the address of a member of a multi-dimensional array, we'll be trying to
            // get the address of a Get method, and it will fail to do so. Instead, detect
            // this situation and replace it with a call to the Address method.
            if (!node.Method.IsStatic &&
                node.Object.Type.IsArray &&
                node.Method == node.Object.Type.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance))
            {
                MethodInfo mi = node.Object.Type.GetMethod("Address", BindingFlags.Public | BindingFlags.Instance);

                EmitMethodCall(node.Object, mi, node);
            }
            else
            {
                EmitExpressionAddress(node, type);
            }
        }
コード例 #27
0
ファイル: TakeSkipBuilder.cs プロジェクト: zabolotnev/linq2db
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
 {
     return(methodCall.IsQueryable("Skip", "Take"));
 }
        protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression)
        {
            if (methodCallExpression.Method.DeclaringType == typeof(Queryable) &&
                methodCallExpression.Method.IsGenericMethod)
            {
                var genericMethod = methodCallExpression.Method.GetGenericMethodDefinition();
                if (genericMethod == QueryableMethods.SelectManyWithCollectionSelector)
                {
                    // SelectMany
                    var selectManySource = methodCallExpression.Arguments[0];
                    if (selectManySource is MethodCallExpression groupJoinMethod &&
                        groupJoinMethod.Method.IsGenericMethod &&
                        groupJoinMethod.Method.GetGenericMethodDefinition() == QueryableMethods.GroupJoin)
                    {
                        // GroupJoin
                        var outer                   = Visit(groupJoinMethod.Arguments[0]);
                        var inner                   = Visit(groupJoinMethod.Arguments[1]);
                        var outerKeySelector        = groupJoinMethod.Arguments[2].UnwrapLambdaFromQuote();
                        var innerKeySelector        = groupJoinMethod.Arguments[3].UnwrapLambdaFromQuote();
                        var groupJoinResultSelector = groupJoinMethod.Arguments[4].UnwrapLambdaFromQuote();

                        var selectManyCollectionSelector = methodCallExpression.Arguments[1].UnwrapLambdaFromQuote();
                        var selectManyResultSelector     = methodCallExpression.Arguments[2].UnwrapLambdaFromQuote();

                        var collectionSelectorBody = selectManyCollectionSelector.Body;
                        var defaultIfEmpty         = false;

                        if (collectionSelectorBody is MethodCallExpression collectionEndingMethod &&
                            collectionEndingMethod.Method.IsGenericMethod &&
                            collectionEndingMethod.Method.GetGenericMethodDefinition() == QueryableMethods.DefaultIfEmptyWithoutArgument)
                        {
                            defaultIfEmpty         = true;
                            collectionSelectorBody = collectionEndingMethod.Arguments[0];
                        }

                        collectionSelectorBody = ReplacingExpressionVisitor.Replace(
                            selectManyCollectionSelector.Parameters[0],
                            groupJoinResultSelector.Body,
                            collectionSelectorBody);

                        var correlatedCollectionSelector = _selectManyVerifyingExpressionVisitor
                                                           .VerifyCollectionSelector(
                            collectionSelectorBody, groupJoinResultSelector.Parameters[1]);

                        if (correlatedCollectionSelector)
                        {
                            var outerParameter       = outerKeySelector.Parameters[0];
                            var innerParameter       = innerKeySelector.Parameters[0];
                            var correlationPredicate = Expression.Equal(
                                outerKeySelector.Body,
                                innerKeySelector.Body);

                            inner = Expression.Call(
                                QueryableMethods.Where.MakeGenericMethod(inner.Type.TryGetSequenceType()),
                                inner,
                                Expression.Quote(Expression.Lambda(correlationPredicate, innerParameter)));

                            inner = ReplacingExpressionVisitor.Replace(
                                groupJoinResultSelector.Parameters[1],
                                inner,
                                collectionSelectorBody);

                            inner = Expression.Quote(Expression.Lambda(inner, outerParameter));
                        }
                        else
                        {
                            inner = _enumerableToQueryableReMappingExpressionVisitor.Visit(
                                ReplacingExpressionVisitor.Replace(
                                    groupJoinResultSelector.Parameters[1],
                                    inner,
                                    collectionSelectorBody));

                            if (inner is MethodCallExpression innerMethodCall &&
                                innerMethodCall.Method.IsGenericMethod &&
                                innerMethodCall.Method.GetGenericMethodDefinition() == QueryableMethods.AsQueryable &&
                                innerMethodCall.Type == innerMethodCall.Arguments[0].Type)
                            {
                                // Remove redundant AsQueryable.
                                // It is fine to leave it in the tree since it is no-op
                                inner = innerMethodCall.Arguments[0];
                            }
                        }

                        var resultSelectorBody = ReplacingExpressionVisitor.Replace(
                            selectManyResultSelector.Parameters[0],
                            groupJoinResultSelector.Body,
                            selectManyResultSelector.Body);

                        var resultSelector = Expression.Lambda(
                            resultSelectorBody,
                            groupJoinResultSelector.Parameters[0],
                            selectManyResultSelector.Parameters[1]);

                        if (correlatedCollectionSelector)
                        {
                            // select many case
                        }
                        else
                        {
                            // join case
                            if (defaultIfEmpty)
                            {
                                // left join
                                return(Expression.Call(
                                           QueryableExtensions.LeftJoinMethodInfo.MakeGenericMethod(
                                               outer.Type.TryGetSequenceType(),
                                               inner.Type.TryGetSequenceType(),
                                               outerKeySelector.ReturnType,
                                               resultSelector.ReturnType),
                                           outer,
                                           inner,
                                           outerKeySelector,
                                           innerKeySelector,
                                           resultSelector));
                            }

                            // inner join
                            return(Expression.Call(
                                       QueryableMethods.Join.MakeGenericMethod(
                                           outer.Type.TryGetSequenceType(),
                                           inner.Type.TryGetSequenceType(),
                                           outerKeySelector.ReturnType,
                                           resultSelector.ReturnType),
                                       outer,
                                       inner,
                                       outerKeySelector,
                                       innerKeySelector,
                                       resultSelector));
                        }
                    }
                }
                else if (genericMethod == QueryableMethods.SelectManyWithoutCollectionSelector)
                {
                    // SelectMany
                    var selectManySource = methodCallExpression.Arguments[0];
                    if (selectManySource is MethodCallExpression groupJoinMethod &&
                        groupJoinMethod.Method.IsGenericMethod &&
                        groupJoinMethod.Method.GetGenericMethodDefinition() == QueryableMethods.GroupJoin)
                    {
                        // GroupJoin
                        var outer                   = Visit(groupJoinMethod.Arguments[0]);
                        var inner                   = Visit(groupJoinMethod.Arguments[1]);
                        var outerKeySelector        = groupJoinMethod.Arguments[2].UnwrapLambdaFromQuote();
                        var innerKeySelector        = groupJoinMethod.Arguments[3].UnwrapLambdaFromQuote();
                        var groupJoinResultSelector = groupJoinMethod.Arguments[4].UnwrapLambdaFromQuote();

                        var selectManyResultSelector = methodCallExpression.Arguments[1].UnwrapLambdaFromQuote();

                        var groupJoinResultSelectorBody = groupJoinResultSelector.Body;
                        var defaultIfEmpty = false;

                        if (groupJoinResultSelectorBody is MethodCallExpression collectionEndingMethod &&
                            collectionEndingMethod.Method.IsGenericMethod &&
                            collectionEndingMethod.Method.GetGenericMethodDefinition() == QueryableMethods.DefaultIfEmptyWithoutArgument)
                        {
                            defaultIfEmpty = true;
                            groupJoinResultSelectorBody = collectionEndingMethod.Arguments[0];
                        }

                        var correlatedCollectionSelector = _selectManyVerifyingExpressionVisitor
                                                           .VerifyCollectionSelector(
                            groupJoinResultSelectorBody, groupJoinResultSelector.Parameters[1]);

                        if (!correlatedCollectionSelector)
                        {
                            inner = ReplacingExpressionVisitor.Replace(
                                groupJoinResultSelector.Parameters[1],
                                inner,
                                groupJoinResultSelectorBody);

                            inner = ReplacingExpressionVisitor.Replace(
                                selectManyResultSelector.Parameters[0],
                                inner,
                                selectManyResultSelector.Body);

                            inner = _enumerableToQueryableReMappingExpressionVisitor.Visit(inner);

                            var resultSelector = Expression.Lambda(
                                innerKeySelector.Parameters[0],
                                groupJoinResultSelector.Parameters[0],
                                innerKeySelector.Parameters[0]);

                            // join case
                            if (defaultIfEmpty)
                            {
                                // left join
                                return(Expression.Call(
                                           QueryableExtensions.LeftJoinMethodInfo.MakeGenericMethod(
                                               outer.Type.TryGetSequenceType(),
                                               inner.Type.TryGetSequenceType(),
                                               outerKeySelector.ReturnType,
                                               resultSelector.ReturnType),
                                           outer,
                                           inner,
                                           outerKeySelector,
                                           innerKeySelector,
                                           resultSelector));
                            }

                            // inner join
                            return(Expression.Call(
                                       QueryableMethods.Join.MakeGenericMethod(
                                           outer.Type.TryGetSequenceType(),
                                           inner.Type.TryGetSequenceType(),
                                           outerKeySelector.ReturnType,
                                           resultSelector.ReturnType),
                                       outer,
                                       inner,
                                       outerKeySelector,
                                       innerKeySelector,
                                       resultSelector));
                        }
                    }
                }
            }

            return(base.VisitMethodCall(methodCallExpression));
        }
コード例 #29
0
        protected override Expression VisitMethodCall(MethodCallExpression m)
        {
            if (m.Method.DeclaringType == typeof(string))
            {
                switch (m.Method.Name)
                {
                case "StartsWith":
                    this.Write("(");
                    this.Visit(m.Object);
                    this.Write(" LIKE " + parameterString);
                    this.Write(_Connector + "'%')");
                    SetParameter(m);
                    return(m);

                case "EndsWith":
                    this.Write("(");
                    this.Visit(m.Object);
                    this.Write(" LIKE '%'" + _Connector + parameterString);
                    this.Write(")");
                    SetParameter(m);
                    return(m);

                case "Contains":
                    this.Write("(");
                    this.Visit(m.Object);
                    this.Write(" LIKE '%'" + _Connector + parameterString);
                    this.Write(_Connector + "'%')");
                    SetParameter(m);
                    return(m);

                case "Concat":
                    IList <Expression> args = m.Arguments;
                    if (args.Count == 1 && args[0].NodeType == ExpressionType.NewArrayInit)
                    {
                        args = ((NewArrayExpression)args[0]).Expressions;
                    }
                    for (int i = 0, n = args.Count; i < n; i++)
                    {
                        if (i > 0)
                        {
                            this.Write(_Connector);
                        }
                        this.Visit(args[i]);
                    }
                    return(m);

                case "IsNullOrEmpty":
                    this.Write("(");
                    this.Visit(m.Object);
                    this.Write(" IS NULL OR ");
                    this.Visit(m.Arguments[0]);
                    this.Write(" = '')");
                    //AddParameter(new DBParameter
                    //{
                    //    Name = ((MemberExpression)m.Object).Member.Name,
                    //    Type = m.Object.GetType().ToString(),
                    //    Size = 100,
                    //    ParameterDirection = ParameterDirection.Input,
                    //    Value = (m.Arguments[0] as ConstantExpression).Value
                    //});
                    SetParameter(m);
                    return(m);

                case "ToUpper":
                    this.Write("UPPER(");
                    this.Visit(m.Object);
                    this.Write(")");
                    return(m);

                case "ToLower":
                    this.Write("LOWER(");
                    this.Visit(m.Object);
                    this.Write(")");
                    return(m);

                case "Replace":
                    this.Write("REPLACE(");
                    this.Visit(m.Object);
                    this.Write(", ");
                    this.Visit(m.Arguments[0]);
                    this.Write(", ");
                    this.Visit(m.Arguments[1]);
                    this.Write(")");
                    return(m);

                case "Substring":
                    this.Write("SUBSTRING(");
                    this.Visit(m.Object);
                    this.Write(", ");
                    this.Visit(m.Arguments[0]);
                    this.Write(" + 1, ");
                    if (m.Arguments.Count == 2)
                    {
                        this.Visit(m.Arguments[1]);
                    }
                    else
                    {
                        this.Write("8000");
                    }
                    this.Write(")");
                    return(m);

                case "Remove":
                    this.Write("STUFF(");
                    this.Visit(m.Object);
                    this.Write(", ");
                    this.Visit(m.Arguments[0]);
                    this.Write(_Connector + "1, ");
                    if (m.Arguments.Count == 2)
                    {
                        this.Visit(m.Arguments[1]);
                    }
                    else
                    {
                        this.Write("8000");
                    }
                    this.Write(", '')");
                    return(m);

                case "IndexOf":
                    this.Write("(CHARINDEX(");
                    this.Visit(m.Arguments[0]);
                    this.Write(", ");
                    this.Visit(m.Object);
                    if (m.Arguments.Count == 2 && m.Arguments[1].Type == typeof(int))
                    {
                        this.Write(", ");
                        this.Visit(m.Arguments[1]);
                        this.Write(_Connector + "1");
                    }
                    this.Write(") - 1)");
                    return(m);

                case "Trim":
                    this.Write("RTRIM(LTRIM(");
                    this.Visit(m.Object);
                    this.Write("))");
                    return(m);
                }
            }
            else if (m.Method.DeclaringType.Name == "List`1")
            {
                switch (m.Method.Name)
                {
                case "Contains":
                    this.Write("(");
                    var position = m.Arguments[0].ToString().IndexOf(".") + 1;
                    var length   = m.Arguments[0].ToString().Length;
                    this.Write(m.Arguments[0].ToString().Substring(position, length - position));
                    this.Visit(m.Object);
                    this.Write(" in (" + inParameterString);
                    this.Write(") )");
                    inParameterString = string.Empty;
                    return(m);
                }
            }
            else if (m.Method.DeclaringType == typeof(DateTime))
            {
                switch (m.Method.Name)
                {
                case "op_Subtract":
                    if (m.Arguments[1].Type == typeof(DateTime))
                    {
                        this.Write("DATEDIFF(");
                        this.Visit(m.Arguments[0]);
                        this.Write(", ");
                        this.Visit(m.Arguments[1]);
                        this.Write(")");
                        return(m);
                    }
                    break;

                case "AddYears":
                    this.Write("DATEADD(YYYY,");
                    this.Visit(m.Arguments[0]);
                    this.Write(",");
                    this.Visit(m.Object);
                    this.Write(")");
                    return(m);

                case "AddMonths":
                    this.Write("DATEADD(MM,");
                    this.Visit(m.Arguments[0]);
                    this.Write(",");
                    this.Visit(m.Object);
                    this.Write(")");
                    return(m);

                case "AddDays":
                    this.Write("DATEADD(DAY,");
                    this.Visit(m.Arguments[0]);
                    this.Write(",");
                    this.Visit(m.Object);
                    this.Write(")");
                    return(m);

                case "AddHours":
                    this.Write("DATEADD(HH,");
                    this.Visit(m.Arguments[0]);
                    this.Write(",");
                    this.Visit(m.Object);
                    this.Write(")");
                    return(m);

                case "AddMinutes":
                    this.Write("DATEADD(MI,");
                    this.Visit(m.Arguments[0]);
                    this.Write(",");
                    this.Visit(m.Object);
                    this.Write(")");
                    return(m);

                case "AddSeconds":
                    this.Write("DATEADD(SS,");
                    this.Visit(m.Arguments[0]);
                    this.Write(",");
                    this.Visit(m.Object);
                    this.Write(")");
                    return(m);

                case "AddMilliseconds":
                    this.Write("DATEADD(MS,");
                    this.Visit(m.Arguments[0]);
                    this.Write(",");
                    this.Visit(m.Object);
                    this.Write(")");
                    return(m);
                }
            }

            else if (m.Method.DeclaringType == typeof(Math))
            {
                switch (m.Method.Name)
                {
                case "Abs":
                case "Acos":
                case "Asin":
                case "Atan":
                case "Cos":
                case "Exp":
                case "Log10":
                case "Sin":
                case "Tan":
                case "Sqrt":
                case "Sign":
                case "Ceiling":
                case "Floor":
                    this.Write(m.Method.Name.ToUpper());
                    this.Write("(");
                    this.Visit(m.Arguments[0]);
                    this.Write(")");
                    return(m);

                case "Atan2":
                    this.Write("ATN2(");
                    this.Visit(m.Arguments[0]);
                    this.Write(", ");
                    this.Visit(m.Arguments[1]);
                    this.Write(")");
                    return(m);

                case "Log":
                    if (m.Arguments.Count == 1)
                    {
                        goto case "Log10";
                    }
                    break;

                case "Pow":
                    this.Write("POWER(");
                    this.Visit(m.Arguments[0]);
                    this.Write(", ");
                    this.Visit(m.Arguments[1]);
                    this.Write(")");
                    return(m);

                case "Round":
                    if (m.Arguments.Count == 1)
                    {
                        this.Write("ROUND(");
                        this.Visit(m.Arguments[0]);
                        this.Write(", 0)");
                        return(m);
                    }
                    else if (m.Arguments.Count == 2 && m.Arguments[1].Type == typeof(int))
                    {
                        this.Write("ROUND(");
                        this.Visit(m.Arguments[0]);
                        this.Write(", ");
                        this.Visit(m.Arguments[1]);
                        this.Write(")");
                        return(m);
                    }
                    break;

                case "Truncate":
                    this.Write("ROUND(");
                    this.Visit(m.Arguments[0]);
                    this.Write(", 0, 1)");
                    return(m);
                }
            }
            if (m.Method.Name == "ToString")
            {
                if (m.Object.Type != typeof(string))
                {
                    this.Write("CONVERT(NVARCHAR, ");
                    this.Visit(m.Object);
                    this.Write(")");
                }
                else
                {
                    this.Visit(m.Object);
                }
                return(m);
            }
            else if (!m.Method.IsStatic && m.Method.Name == "CompareTo" && m.Method.ReturnType == typeof(int) && m.Arguments.Count == 1)
            {
                this.Write("(CASE WHEN ");
                this.Visit(m.Object);
                this.Write(" = ");
                this.Visit(m.Arguments[0]);
                this.Write(" THEN 0 WHEN ");
                this.Visit(m.Object);
                this.Write(" < ");
                this.Visit(m.Arguments[0]);
                this.Write(" THEN -1 ELSE 1 END)");
                return(m);
            }
            else if (m.Method.IsStatic && m.Method.Name == "Compare" && m.Method.ReturnType == typeof(int) && m.Arguments.Count == 2)
            {
                this.Write("(CASE WHEN ");
                this.Visit(m.Arguments[0]);
                this.Write(" = ");
                this.Visit(m.Arguments[1]);
                this.Write(" THEN 0 WHEN ");
                this.Visit(m.Arguments[0]);
                this.Write(" < ");
                this.Visit(m.Arguments[1]);
                this.Write(" THEN -1 ELSE 1 END)");
                return(m);
            }
            return(base.VisitMethodCall(m));
        }
コード例 #30
0
        public override Expression Visit(BinaryOperatorNode nodeIn)
        {
            Expression left  = TranslateNode(nodeIn.Left);
            Expression right = TranslateNode(nodeIn.Right);

            if (left.Type != right.Type)
            {
                Type leftType  = left.Type;
                Type rightType = right.Type;

                if (OeExpressionHelper.IsNullable(left) && !OeExpressionHelper.IsNull(left))
                {
                    if (OeExpressionHelper.IsNull(right))
                    {
                        right = OeConstantToVariableVisitor.NullConstantExpression;
                    }
                    else
                    {
                        leftType = Nullable.GetUnderlyingType(left.Type);
                    }
                }
                else if (OeExpressionHelper.IsNullable(right) && !OeExpressionHelper.IsNull(right))
                {
                    if (OeExpressionHelper.IsNull(left))
                    {
                        left = OeConstantToVariableVisitor.NullConstantExpression;
                    }
                    else
                    {
                        rightType = Nullable.GetUnderlyingType(right.Type);
                    }
                }

                if (right.Type != left.Type)
                {
                    if (left is ConstantExpression)
                    {
                        ConstantExpression oldConstant = left as ConstantExpression;
                        ConstantExpression newConstant = OeExpressionHelper.ConstantChangeType(oldConstant, rightType);
                        if (oldConstant != newConstant)
                        {
                            ReplaceConstant(oldConstant, newConstant);
                        }
                        left = Expression.Convert(newConstant, right.Type);
                    }
                    else if (right is ConstantExpression)
                    {
                        ConstantExpression oldConstant = right as ConstantExpression;
                        ConstantExpression newConstant = OeExpressionHelper.ConstantChangeType(oldConstant, leftType);
                        if (oldConstant != newConstant)
                        {
                            ReplaceConstant(oldConstant, newConstant);
                        }
                        right = Expression.Convert(newConstant, left.Type);
                    }
                    else
                    {
                        Type precedenceType = OeExpressionHelper.GetTypeConversion(left.Type, right.Type);
                        if (left.Type != precedenceType)
                        {
                            left = Expression.Convert(left, precedenceType);
                        }
                        if (right.Type != precedenceType)
                        {
                            right = Expression.Convert(right, precedenceType);
                        }
                    }
                }
            }
            ExpressionType binaryType = OeExpressionHelper.ToExpressionType(nodeIn.OperatorKind);

            if (!(binaryType == ExpressionType.Equal || binaryType == ExpressionType.NotEqual))
            {
                if (left.Type == typeof(String))
                {
                    Func <String, String, int> compareToFunc = String.Compare;
                    MethodCallExpression       compareToCall = Expression.Call(null, compareToFunc.GetMethodInfo(), left, right);
                    return(Expression.MakeBinary(binaryType, compareToCall, OeConstantToVariableVisitor.ZeroStringCompareConstantExpression));
                }

                Type underlyingType;
                if (left.Type.IsEnum)
                {
                    Type enumUnderlyingType = Enum.GetUnderlyingType(left.Type);
                    left  = ConvertEnumExpression(left, enumUnderlyingType);
                    right = ConvertEnumExpression(right, enumUnderlyingType);
                }
                else if ((underlyingType = Nullable.GetUnderlyingType(left.Type)) != null && underlyingType.IsEnum)
                {
                    Type enumUnderlyingType     = Enum.GetUnderlyingType(underlyingType);
                    Type nullableUnderlyingType = typeof(Nullable <>).MakeGenericType(enumUnderlyingType);
                    left  = ConvertEnumExpression(left, nullableUnderlyingType);
                    right = ConvertEnumExpression(right, nullableUnderlyingType);
                }
            }

            return(Expression.MakeBinary(binaryType, left, right));

            UnaryExpression ConvertEnumExpression(Expression e, Type nullableType)
            {
                if (e is UnaryExpression unaryExpression)
                {
                    var value = (ConstantExpression)unaryExpression.Operand;
                    return(Expression.Convert(value, nullableType));
                }

                return(Expression.Convert(e, nullableType));
            }
        }
コード例 #31
0
 protected override Expression VisitMethodCall(MethodCallExpression expr)
 {
     Type = BinaryCriterionType.Criteria;
     return(expr);
 }
コード例 #32
0
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
 {
     return(methodCall.IsSameGenericMethod(UsingTargetMethodInfo));
 }
コード例 #33
0
        protected override Expression VisitMethodCall(MethodCallExpression m)
        {
            if (m.Method.DeclaringType == typeof(Queryable) ||
                m.Method.DeclaringType == typeof(Enumerable))
            {
                switch (m.Method.Name)
                {
                case "Where":
                    WhereArgumentsVisitor vst = new WhereArgumentsVisitor(rootCriteria);
                    System.Linq.Expressions.Expression exp = vst.Visit(m.Arguments[1]);
                    rootCriteria.Add(vst.CurrentCriterions[0]);

                    break;

                case "Select":
                    HandleSelect(m);
                    break;

                case "First":
                    TranslateFirst(m, false);
                    break;

                case "FirstOrDefault":
                    TranslateFirst(m, true);
                    break;

                case "Single":
                    TranslateSingle(m, false);
                    break;

                case "SingleOrDefault":
                    TranslateSingle(m, true);
                    break;

                case "Count":
                    Translation = new CountQueryTranslated(this)
                    {
                        Criteria = rootCriteria
                    };
                    break;

                case "Sum":
                    HandleProjectionOfSingleElement(m, s => NHEX.Projections.Sum(s));
                    break;

                case "Min":
                    HandleProjectionOfSingleElement(m, s => NHEX.Projections.Min(s));
                    break;

                case "Max":
                    HandleProjectionOfSingleElement(m, s => NHEX.Projections.Max(s));
                    break;

                case "Average":
                    HandleProjectionOfSingleElement(m, s => NHEX.Projections.Avg(s));
                    break;

                case "GroupBy":
                    HandleGroupBy(m);
                    break;

                default:
                    Console.WriteLine("Unknown method " + m.Method.Name);
                    break;
                }
            }
            return(base.VisitMethodCall(m));
        }
コード例 #34
0
        private static IValueExpression ParseMethodCall(string expression)
        {
            MethodCallExpression methodCall = null;

            int openParenIndex = expression.IndexOf("(", StringComparison.Ordinal);
            string memberExpression = expression.Substring(0, openParenIndex);

            string[] pathParts = ParseParts(memberExpression);
            if ((pathParts != null) && (pathParts.Length >= 2)) {
                methodCall = new MethodCallExpression(pathParts);
            }
            else {
                return null;
            }

            int paramsLength = expression.Length - openParenIndex - 2;
            if (paramsLength != 0) {
                string paramExpression = expression.Substring(openParenIndex + 1, paramsLength);
                string[] paramExprList = paramExpression.Split(',');

                for (int i = 0; i < paramExprList.Length; i++) {
                    IValueExpression expr = ParseExpression(paramExprList[i].Trim(), /* allowMethod */ false);
                    if (expr != null) {
                        methodCall.AddParameter(expr);
                    }
                    else {
                        return null;
                    }
                }
            }

            return methodCall;
        }
コード例 #35
0
        public Expression Bind(PipelineExpression pipeline, EmbeddedPipelineBindingContext bindingContext, MethodCallExpression node, IEnumerable <Expression> arguments)
        {
            var source = pipeline.Source;

            if (arguments.Any())
            {
                source = BinderHelper.BindSelect(
                    pipeline,
                    bindingContext,
                    ExpressionHelper.GetLambda(arguments.Single()));
            }

            return(new PipelineExpression(
                       source,
                       pipeline.Projector,
                       new AverageResultOperator(
                           node.Type,
                           bindingContext.GetSerializer(node.Type, node))));
        }
コード例 #36
0
 protected virtual Expression VisitMethodCall(MethodCallExpression m)
 {
     Expression obj = this.Visit(m.Object);
     IEnumerable<Expression> args = this.VisitExpressionList(m.Arguments);
     return this.UpdateMethodCall(m, obj, m.Method, args);
 }
コード例 #37
0
 /// <summary>
 /// 构造函数
 /// </summary>
 /// <param name="node">静态方法或实例方法表达式树</param>
 public MethodCallVisitor(MethodCallExpression node)
 {
     this.node = node;
 }
コード例 #38
0
        static bool TryUncheckedCast(MethodCallExpression node, ref Expression rewrite)
        {
            MethodInfo info = node.Method;
            Type decType = info.DeclaringType;
            string name = info.Name;

            if (decType == typeof(RT))
            {
                if (name.StartsWith("unchecked") && name.EndsWith("Cast"))
                {
                    ParameterInfo[] pinfos = info.GetParameters();
                    if (pinfos.Length == 1 && pinfos[0].ParameterType != typeof(object))
                    {
                        rewrite = Expression.Convert(node.Arguments[0], info.ReturnType);
                        return true;
                    }
                }
            }
            else if (decType == typeof(Util))
            {
                if (name == "identical")
                {
                    ParameterExpression param1 = Expression.Parameter(typeof(Object), "temp1");
                    ParameterExpression param2 = Expression.Parameter(typeof(Object), "temp2");

                    rewrite = Expression.Block(typeof(bool), new ParameterExpression[] { param1, param2 },
                        Expression.Assign(param1, node.Arguments[0]),
                        Expression.Assign(param2, node.Arguments[1]),
                        Expression.Condition(
                            Expression.TypeIs(param1, typeof(ValueType)),
                            Expression.Call(param1, typeof(object).GetMethod("Equals", new Type[] { typeof(object) }), param2),
                            Expression.ReferenceEqual(param1, param2)));
                    return true;
                }
            }
            else if (decType == typeof(Numbers))
            {
                ParameterInfo[] pinfos = info.GetParameters();

                bool argsOk = (pinfos.Length == 1 && (pinfos[0].ParameterType == typeof(double) || pinfos[0].ParameterType == typeof(long)))
                    || (pinfos.Length == 2 && (pinfos[0].ParameterType == typeof(double) || pinfos[0].ParameterType == typeof(long)) && pinfos[0].ParameterType == pinfos[1].ParameterType);
                if (argsOk)
                {
                    switch (name)
                    {
                        case "lt":
                            rewrite = Expression.LessThan(node.Arguments[0], node.Arguments[1]);
                            return true;
                        case "lte":
                            rewrite = Expression.LessThanOrEqual(node.Arguments[0], node.Arguments[1]);
                            return true;
                        case "gt":
                            rewrite = Expression.GreaterThan(node.Arguments[0], node.Arguments[1]);
                            return true;
                        case "gte":
                            rewrite = Expression.GreaterThanOrEqual(node.Arguments[0], node.Arguments[1]);
                            return true;
                        case "isPos":
                            rewrite = Expression.GreaterThan(node.Arguments[0], Expression.Constant(pinfos[0].ParameterType == typeof(double) ? (object)0.0 : (object)0L));
                            return true;
                        case "isNeg":
                            rewrite = Expression.LessThan(node.Arguments[0], Expression.Constant(pinfos[0].ParameterType == typeof(double) ? (object)0.0 : (object)0L));
                            return true;
                        case "isZero":
                            rewrite = Expression.Equal(node.Arguments[0], Expression.Constant(pinfos[0].ParameterType == typeof(double) ? (object)0.0 : (object)0L));
                            return true;
                        case "equiv":
                            rewrite = Expression.Equal(node.Arguments[0], node.Arguments[1]);
                            return true;
                        case "unchecked_add":
                            rewrite = Expression.Add(node.Arguments[0], node.Arguments[1]);
                            return true;
                        case "unchecked_minus":
                            if (pinfos.Length == 1)
                                rewrite = Expression.Negate(node.Arguments[0]);
                            else
                                rewrite = Expression.Subtract(node.Arguments[0], node.Arguments[1]);
                            return true;
                        case "unchecked_multiply":
                            rewrite = Expression.Multiply(node.Arguments[0], node.Arguments[1]);
                            return true;
                        case "unchecked_inc":
                            rewrite = Expression.Increment(node.Arguments[0]);
                            return true;
                        case "unchecked_dec":
                            rewrite = Expression.Decrement(node.Arguments[0]);
                            return true;
                    }

                    if (pinfos[0].ParameterType == typeof(double))
                    {
                        switch (name)
                        {
                            case "add":
                            case "addP":
                                rewrite = Expression.Add(node.Arguments[0], node.Arguments[1]);
                                return true;
                            case "multiply":
                            case "multiplyP":
                                rewrite = Expression.Multiply(node.Arguments[0], node.Arguments[1]);
                                return true;
                            case "divide":
                                rewrite = Expression.Divide(node.Arguments[0], node.Arguments[1]);
                                return true;
                            case "minus":
                            case "minusP":
                                if (pinfos.Length == 1)
                                    rewrite = Expression.Negate(node.Arguments[0]);
                                else
                                    rewrite = Expression.Subtract(node.Arguments[0], node.Arguments[1]);
                                return true;
                            case "inc":
                            case "incP":
                                rewrite = Expression.Increment(node.Arguments[0]);
                                return true;
                            case "dec":
                            case "decP":
                                rewrite = Expression.Decrement(node.Arguments[0]);
                                return true;
                        }
                    }
                    else // long
                    {
                        switch (name)
                        {
                            case "quotient":
                                rewrite = Expression.Divide(node.Arguments[0], node.Arguments[1]);
                                return true;
                            case "remainder":
                                rewrite = Expression.Modulo(node.Arguments[0], node.Arguments[1]);
                                return true;
                        }
                    }
                }
            }

            return false;
        }
コード例 #39
0
ファイル: ExpressionMutator.cs プロジェクト: kouweizhong/vita
        }//method

        static MethodCallExpression MutateMethodCall(MethodCallExpression node, IList <Expression> operands)
        {
            var args = operands.Skip(1);

            return(node.Update(operands[0], args));
        }
コード例 #40
0
 private string GetMethodReturnType(MethodCallExpression expression)
 {
     string result = String.Empty;
     switch (expression.Parent.ElementType)
     {
         case LanguageElementType.MethodCall:
             var MethodCall = expression.Parent as MethodCall;
             var index = MethodCall.Arguments.IndexOf(expression);
             result = GetTypeOfNthParamOfMethod(index, MethodCall);
             break;
         case LanguageElementType.MethodCallExpression:
             var MethodCallExpression = expression.Parent as MethodCallExpression;
             var MCEindex = MethodCallExpression.Arguments.IndexOf(expression);
             result = GetTypeOfNthParamOfMethod(MCEindex, MethodCallExpression);
             break;
         case LanguageElementType.InitializedVariable:
             result = GetTypeOfInitializedVariable(expression.Parent as InitializedVariable);
             break;
         case LanguageElementType.Assignment:
             result = GetTypeOfAssignment(expression.Parent as Assignment);
             break;
         default:
             throw new Exception("");
     }
     return CodeRush.Language.GetSimpleTypeName(result);
 }
コード例 #41
0
ファイル: MergeBuilder.cs プロジェクト: zabolotnev/linq2db
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var mergeContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            return(mergeContext);
        }
コード例 #42
0
		public abstract object EvalMethodCallExpression( object obj, MethodCallExpression exp );
コード例 #43
0
ファイル: MergeBuilder.cs プロジェクト: zabolotnev/linq2db
 protected override SequenceConvertInfo?Convert(
     ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression?param)
 {
     return(null);
 }
コード例 #44
0
        private static void AssertCallIsOptimized(MethodCallExpression expr, Expression instance, MethodInfo method, IReadOnlyList<Expression> args)
        {
            var n = method.GetParameters().Length;

            var updated = Update(expr);
            var visited = Visit(expr);

            foreach (var node in new[] { expr, updated, visited })
            {
                Assert.Same(instance, node.Object);
                Assert.Same(method, node.Method);

                if (method.IsStatic)
                {
                    AssertStaticMethodCall(n, node);
                }
                else
                {
                    AssertInstanceMethodCall(n, node);
                }

                var argProvider = node as IArgumentProvider;
                Assert.NotNull(argProvider);

                Assert.Equal(n, argProvider.ArgumentCount);

                if (node != visited) // our visitor clones argument nodes
                {
                    for (var i = 0; i < n; i++)
                    {
                        Assert.Same(args[i], argProvider.GetArgument(i));
                        Assert.Same(args[i], node.Arguments[i]);
                    }
                }
            }
        }
コード例 #45
0
ファイル: MergeBuilder.cs プロジェクト: zabolotnev/linq2db
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
 {
     return(methodCall.Method.IsGenericMethod &&
            LinqExtensions.ExecuteMergeMethodInfo == methodCall.Method.GetGenericMethodDefinition());
 }
コード例 #46
0
ファイル: ExpressionEvaluator.cs プロジェクト: jmclain/Nmp
		/////////////////////////////////////////////////////////////////////////////

		//public override object EvalMethodCallExpression( object objIn, MethodCallExpression exp )
		//{
		//	// ******
		//	//
		//	// expression:  macro.method(..)
		//	//
		//	// exp.MemberName should be a method on the object passed in to us, it is the
		//	// method that we need to retreive and then invoke
		//	//
		//	object objResult = null;
		//	object [] args = EvaluateArguments( exp.Arguments );
		//	
		//	// ******
		//	Invoker invoker = Invokers.GetMethodInvoker( objIn, exp.MethodName );
		//	if( null != invoker ) {
		//		objResult = invoker.Invoke( args );
		//	}
		//	else {
		//		//
		//		// could be a "raw" delegate
		//		//
		//		var oInfo = new ObjectInfo( objIn, exp.MethodName );
		//		if( oInfo.IsDelegate ) {
		//			objResult = oInfo.GetDelegateValue( args );
		//		}
		//		else {
		//			ThreadContext.MacroError( "there is no method or delegate named \"{0}\" on the object type \"{1}\"", exp.MethodName, ObjectInfo.GetTypeName(objIn) );
		//		}
		//	}
		//
		//	// ******
		//	CheckNullResult( objResult, objIn, exp.MethodName );
		//	return objResult;
		//}


		public override object EvalMethodCallExpression( object objIn, MethodCallExpression exp )
		{
			// ******
			//
			// expression:  macro.method(..)
			//
			// exp.MemberName should be a method on the object passed in to us, it is the
			// method that we need to retreive and then invoke
			//
			object objResult = null;
			object [] args = EvaluateArguments( exp.Arguments );
			
			// ******
			//Invoker invoker = Invokers.GetMethodInvoker( objIn, exp.MethodName );
			Invoker invoker = Invokers.GetMethodInvoker( objIn, exp.MethodName, typeHelpers );
			if( null != invoker ) {
				objResult = invoker.Invoke( args );
			}
			else {
				//
				// could be a "raw" delegate
				//
				var oInfo = new ObjectInfo( objIn, exp.MethodName );
				if( oInfo.IsDelegate ) {
					objResult = oInfo.GetDelegateValue( args );
				}
				else {
					ThreadContext.MacroError( "there is no method or delegate named \"{0}\" on the object type \"{1}\"", exp.MethodName, ObjectInfo.GetTypeName(objIn) );
				}
			}

			// ******
			CheckNullResult( objResult, objIn, exp.MethodName );
			return objResult;
		}
コード例 #47
0
ファイル: ExpressionHelper.cs プロジェクト: ciker/DataCore
        public static bool GetSqlExtensionMethodCallConstant(ITranslator translator, MethodCallExpression methodExpression, Parameters parameters, out string concat)
        {
            if (methodExpression.Method.Name == "Min" && methodExpression.Method.ReflectedType.Name == "SqlExtensions")
            {
                concat = string.Concat("MIN(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ")");
                return(true);
            }

            if (methodExpression.Method.Name == "Max" && methodExpression.Method.ReflectedType.Name == "SqlExtensions")
            {
                concat = string.Concat("MAX(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ")");
                return(true);
            }

            if (methodExpression.Method.Name == "Sum" && methodExpression.Method.ReflectedType.Name == "SqlExtensions")
            {
                concat = string.Concat("SUM(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ")");
                return(true);
            }

            if (methodExpression.Method.Name == "As" && methodExpression.Method.ReflectedType.Name == "SqlExtensions")
            {
                var aliasFormat = translator.GetAliasFormat();
                var alias       = string.Format(aliasFormat,
                                                Convert.ToString(methodExpression.Arguments[1]).Replace("\"", "").Replace("'", ""));

                concat = string.Concat(GetStringForExpression(translator, methodExpression.Arguments[0], parameters), " AS ", alias);
                return(true);
            }

            if (methodExpression.Method.Name == "Between" && methodExpression.Method.ReflectedType.Name == "SqlExtensions")
            {
                concat = string.Concat("(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), " BETWEEN ",
                                       GetStringForExpression(translator, methodExpression.Arguments[1], parameters), " AND ",
                                       GetStringForExpression(translator, methodExpression.Arguments[2], parameters), ")");
                return(true);
            }

            if (methodExpression.Method.Name == "In" && methodExpression.Method.ReflectedType.Name == "SqlExtensions")
            {
                concat = string.Concat("(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), " IN (",
                                       GetStringForExpression(translator, methodExpression.Arguments[1], parameters), "))");

                return(true);
            }

            if (methodExpression.Method.Name == "Like" && methodExpression.Method.ReflectedType.Name == "SqlExtensions")
            {
                concat = string.Concat("(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), " LIKE ",
                                       GetStringForExpression(translator, methodExpression.Arguments[1], parameters), ")");

                return(true);
            }

            if (methodExpression.Method.Name == "TrimSql" && methodExpression.Method.ReflectedType.Name == "SqlExtensions")
            {
                concat = string.Concat("LTRIM(RTRIM(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), "))");

                return(true);
            }

            if (methodExpression.Method.Name == "Length" && methodExpression.Method.ReflectedType.Name == "SqlExtensions")
            {
                var lengthName = translator.GetLengthFunctionName();

                concat = string.Concat(lengthName, "(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ")");

                return(true);
            }

            if (methodExpression.Method.Name == "Upper" && methodExpression.Method.ReflectedType.Name == "SqlExtensions")
            {
                concat = string.Concat("UPPER(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ")");

                return(true);
            }

            if (methodExpression.Method.Name == "Lower" && methodExpression.Method.ReflectedType.Name == "SqlExtensions")
            {
                concat = string.Concat("LOWER(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ")");

                return(true);
            }

            if (methodExpression.Method.Name == "IsNull" && methodExpression.Method.ReflectedType.Name == "SqlExtensions")
            {
                var isNullName = translator.GetIsNullFunctionName();

                concat = string.Concat(isNullName, "(",
                                       GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ",",
                                       GetStringForExpression(translator, methodExpression.Arguments[1], parameters), ")");

                return(true);
            }

            if (methodExpression.Method.Name == "Cast" && methodExpression.Method.ReflectedType.Name == "SqlExtensions")
            {
                var returnDbType = TableDefinition.GetTypeForProperty(methodExpression.Method.ReturnType);

                concat = string.Concat("CAST(",
                                       GetStringForExpression(translator, methodExpression.Arguments[0], parameters), " AS ",
                                       translator.GetTextFor(new FieldDefinition {
                    Type = returnDbType
                }, true), ")");

                return(true);
            }

            if (methodExpression.Method.Name == "Average" && methodExpression.Method.ReflectedType.Name == "SqlExtensions")
            {
                concat = string.Concat("AVG(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ")");

                return(true);
            }

            concat = "";
            return(false);
        }
コード例 #48
0
ファイル: CallFactoryTests.cs プロジェクト: dotnet/corefx
        private static MethodCallExpression UpdateArgs(MethodCallExpression node)
        {
            // Tests the call of Update to Expression.Call factories.

            MethodCallExpression res = node.Update(node.Object, node.Arguments.ToArray());

            Assert.NotSame(node, res);

            return res;
        }
コード例 #49
0
 protected override Expression VisitSQLNewGuid(MethodCallExpression m)
 {
     _builder.Append("SYS_GUID()");
     return(m);
 }
コード例 #50
0
ファイル: CallFactoryTests.cs プロジェクト: dotnet/corefx
        private static MethodCallExpression VisitObj(MethodCallExpression node)
        {
            // Tests dispatch of ExpressionVisitor into Rewrite method which calls Expression.Call factories.

            return (MethodCallExpression)new VisitorObj().Visit(node);
        }
コード例 #51
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            if (node.Method.DeclaringType == typeof(Queryable) && node.Method.Name == "Select")
            {
                var select     = Visit(node.Arguments[0]);
                var projection = Visit(StripQuotes(node.Arguments[1])) as LambdaExpression;

                if (projection == null)
                {
                    throw new NotSupportedException("Performing a select without a lambda is not supported");
                }

                return(new SelectExpression(node.Type, select, projection));
            }

            if (node.Method.DeclaringType == typeof(Queryable) && node.Method.Name == "Where")
            {
                var select = Visit(node.Arguments[0]);
                var filter = Visit(StripQuotes(node.Arguments[1]));

                return(new WhereExpression(node.Type, select, filter));
            }

            if (node.Method.DeclaringType == typeof(Queryable) && (node.Method.Name == "OrderBy" || node.Method.Name == "ThenBy"))
            {
                var source        = Visit(node.Arguments[0]);
                var orderSelector = Visit(StripQuotes(node.Arguments[1]));

                return(new OrderExpression(node.Type, source, orderSelector, OrderOptions.Ascending));
            }

            if (node.Method.DeclaringType == typeof(Queryable) && (node.Method.Name == "OrderByDescending" || node.Method.Name == "ThenByDescending"))
            {
                var source        = Visit(node.Arguments[0]);
                var orderSelector = Visit(StripQuotes(node.Arguments[1]));

                return(new OrderExpression(node.Type, source, orderSelector, OrderOptions.Descending));
            }

            if (node.Method.DeclaringType == typeof(string) && node.Method.Name == "StartsWith")
            {
                var subject = Visit(node.Object);
                var target  = Visit(node.Arguments[0]);

                return(new UnderExpression(node.Type, subject, target));
            }

            if (node.Method.DeclaringType == typeof(QueryExtensions) && node.Method.Name == "WasEver")
            {
                var subject = Visit(node.Arguments[0]);
                var target  = Visit(node.Arguments[1]);

                return(new WasEverExpression(node.Type, subject, target));
            }

            if (node.Method.DeclaringType == typeof(QueryExtensions) && node.Method.Name == "InGroup")
            {
                var subject = Visit(node.Arguments[0]);
                var target  = Visit(node.Arguments[1]);

                return(new InGroupExpression(node.Type, subject, target));
            }

            if (node.Method.DeclaringType == typeof(QueryExtensions) && node.Method.Name == "NotInGroup")
            {
                var subject = Visit(node.Arguments[0]);
                var target  = Visit(node.Arguments[1]);

                return(new NotInGroupExpression(node.Type, subject, target));
            }

            // This is a contains used to see if a value is in a list, such as: bug => aliases.Contains(bug.AssignedTo)
            if (node.Method.DeclaringType == typeof(Enumerable) && node.Method.Name == "Contains")
            {
                var subject = Visit(node.Arguments[1]);
                var target  = Visit(node.Arguments[0]);

                return(new InExpression(node.Type, subject, target));
            }

            // This is a contains used to do substring matching on a value, such as: bug => bug.Status.Contains("Approved")
            if (node.Method.DeclaringType == typeof(string) && node.Method.Name == "Contains")
            {
                var subject = Visit(node.Object);
                var target  = Visit(node.Arguments[0]);

                return(new ContainsExpression(node.Type, subject, target));
            }

            if (node.Method.DeclaringType == typeof(QueryExtensions) && node.Method.Name == "AsOf")
            {
                Visit(node.Arguments[0]);
                var time = (ConstantExpression)Visit(node.Arguments[1]);

                return(new AsOfExpression(node.Type, (DateTime)time.Value));
            }

            if (node.Method.Name == "ToUpper" || node.Method.Name == "ToUpperInvariant" || node.Method.Name == "ToLower" || node.Method.Name == "ToLowerInvariant")
            {
                throw new NotSupportedException($"The method {node.Method.Name} is not supported. Queries are case insensitive, so string comparisons should use the regular operators ( ==, > <=, etc.)");
            }

            if (node.Method.Name == "ToString")
            {
                return(Expression.TypeAs(Visit(node.Object), typeof(string)));
            }

            if (node.Method.Name == "get_Item")
            {
                var subject = node.Object;
                var name    = Visit(node.Arguments[0]);
                return(new IndexerExpression(node.Type, subject, name));
            }

            // Unknown method call
            throw new NotSupportedException($"The method '{node.Method.Name}' is not supported");
        }
コード例 #52
0
 protected internal virtual void PostWalk(MethodCallExpression node) { }
コード例 #53
0
ファイル: Criterion.From.cs プロジェクト: tohfe/Olive
        public static Criterion From(MethodCallExpression expression, bool throwOnError = true)
        {
            Expression       valueExpression = null;
            MemberExpression propertyExpression;
            FilterFunction   filter;
            string           sql = null;

            if (expression.Method == StringContainsMethod)
            {
                propertyExpression = expression.Object as MemberExpression;
                valueExpression    = expression.Arguments[0];
                filter             = FilterFunction.Contains;
            }
            else if (expression.Method == StringContainsExtensionMethod)
            {
                propertyExpression = expression.Arguments[0] as MemberExpression;
                valueExpression    = expression.Arguments[1];
                filter             = FilterFunction.Contains;
            }
            else if (expression.Method == StringIsEmptyExtensionMethod)
            {
                propertyExpression = expression.Arguments[0] as MemberExpression;
                var column = propertyExpression.GetDatabaseColumnPath();

                return(new BinaryCriterion(new Criterion(column, value: null),
                                           BinaryOperator.OR, new Criterion(column, string.Empty)));
            }
            else if (expression.Method == StringHasValueExtensionMethod)
            {
                propertyExpression = expression.Arguments[0] as MemberExpression;
                var column = propertyExpression.GetDatabaseColumnPath();

                return(new BinaryCriterion(new Criterion(column, FilterFunction.IsNot, value: null),
                                           BinaryOperator.AND, new Criterion(column, FilterFunction.IsNot, string.Empty)));
            }
            else if (expression.Method == StringLacksExtensionMethod)
            {
                propertyExpression = expression.Arguments[0] as MemberExpression;
                valueExpression    = expression.Arguments[1];
                filter             = FilterFunction.NotContains;
            }
            else if (expression.Method == StringStartsWithMethod)
            {
                propertyExpression = expression.Object as MemberExpression;
                valueExpression    = expression.Arguments[0];
                filter             = FilterFunction.BeginsWith;
            }
            else if (expression.Method == StringEndsWithMethod)
            {
                propertyExpression = expression.Object as MemberExpression;
                valueExpression    = expression.Arguments[0];
                filter             = FilterFunction.EndsWith;
            }
            else if (expression.Method.Name == "IsAnyOf")
            {
                propertyExpression = expression.Arguments.First() as MemberExpression;
                valueExpression    = expression.Arguments[1];
                filter             = FilterFunction.In;
            }
            else if (expression.Method.Name == "IsNoneOf")
            {
                propertyExpression = expression.Arguments.First() as MemberExpression;
                valueExpression    = expression.Arguments[1];
                filter             = FilterFunction.NotIn;
            }
            else
            {
                if (!throwOnError)
                {
                    return(null);
                }

                throw new ArgumentException("Invalid database criteria. The provided filter expression cannot be evaluated and converted into a SQL condition.");
            }

            if (propertyExpression == null || !(propertyExpression.Member is PropertyInfo))
            {
                if (!throwOnError)
                {
                    return(null);
                }

                throw new ArgumentException("Invalid database criteria. The provided filter expression cannot be evaluated and converted into a SQL condition." +
                                            expression + Environment.NewLine + Environment.NewLine + "Consider using application level filter using the \".Where(...)\" clause.");
            }

            var property = propertyExpression.Member.Name;

            // Middle properties?
            while (propertyExpression.Expression is MemberExpression)
            {
                propertyExpression = propertyExpression.Expression as MemberExpression;
                property           = propertyExpression.Member.Name + "." + property;
            }

            if (sql.HasValue())
            {
                if (property.Contains("."))
                {
                    return(null);                        // Nesting is not supported.
                }
                return(new DirectDatabaseCriterion(sql.Replace("#PROPERTY#", property))
                {
                    PropertyName = property
                });
            }
            else
            {
                var value = Expression.Lambda(valueExpression).Compile().DynamicInvoke();

                if (!(value is string) && value is IEnumerable asEnum)
                {
                    Func <object, string> escape = x => $"'{x}'";
                    if (asEnum.GetType().GetEnumerableItemType().IsBasicNumeric())
                    {
                        escape = x => x.ToString();
                    }

                    if (asEnum.GetType().GetEnumerableItemType().Implements <IEntity>())
                    {
                        escape = x => $"'{(x as IEntity).GetId()}'";
                    }

                    if (asEnum.GetType().GetEnumerableItemType().IsEnum)
                    {
                        escape = x => ((int)x).ToString();
                    }

                    value = $"({asEnum.Cast<object>().Select(escape).ToString(",")})";
                }

                return(new Criterion(property, filter, value));
            }
        }
コード例 #54
0
        private void EmitLift(ExpressionType nodeType, Type resultType, MethodCallExpression mc, ParameterExpression[] paramList, Expression[] argList)
        {
            Debug.Assert(TypeUtils.AreEquivalent(TypeUtils.GetNonNullableType(resultType), TypeUtils.GetNonNullableType(mc.Type)));

            switch (nodeType)
            {
                default:
                case ExpressionType.LessThan:
                case ExpressionType.LessThanOrEqual:
                case ExpressionType.GreaterThan:
                case ExpressionType.GreaterThanOrEqual:
                    {
                        Label exit = _ilg.DefineLabel();
                        Label exitNull = _ilg.DefineLabel();
                        LocalBuilder anyNull = _ilg.DeclareLocal(typeof(bool));
                        for (int i = 0, n = paramList.Length; i < n; i++)
                        {
                            ParameterExpression v = paramList[i];
                            Expression arg = argList[i];
                            if (TypeUtils.IsNullableType(arg.Type))
                            {
                                _scope.AddLocal(this, v);
                                EmitAddress(arg, arg.Type);
                                _ilg.Emit(OpCodes.Dup);
                                _ilg.EmitHasValue(arg.Type);
                                _ilg.Emit(OpCodes.Ldc_I4_0);
                                _ilg.Emit(OpCodes.Ceq);
                                _ilg.Emit(OpCodes.Stloc, anyNull);
                                _ilg.EmitGetValueOrDefault(arg.Type);
                                _scope.EmitSet(v);
                            }
                            else
                            {
                                _scope.AddLocal(this, v);
                                EmitExpression(arg);
                                if (!arg.Type.GetTypeInfo().IsValueType)
                                {
                                    _ilg.Emit(OpCodes.Dup);
                                    _ilg.Emit(OpCodes.Ldnull);
                                    _ilg.Emit(OpCodes.Ceq);
                                    _ilg.Emit(OpCodes.Stloc, anyNull);
                                }
                                _scope.EmitSet(v);
                            }
                            _ilg.Emit(OpCodes.Ldloc, anyNull);
                            _ilg.Emit(OpCodes.Brtrue, exitNull);
                        }
                        EmitMethodCallExpression(mc);
                        if (TypeUtils.IsNullableType(resultType) && !TypeUtils.AreEquivalent(resultType, mc.Type))
                        {
                            ConstructorInfo ci = resultType.GetConstructor(new Type[] { mc.Type });
                            _ilg.Emit(OpCodes.Newobj, ci);
                        }
                        _ilg.Emit(OpCodes.Br_S, exit);
                        _ilg.MarkLabel(exitNull);
                        if (TypeUtils.AreEquivalent(resultType, TypeUtils.GetNullableType(mc.Type)))
                        {
                            if (resultType.GetTypeInfo().IsValueType)
                            {
                                LocalBuilder result = GetLocal(resultType);
                                _ilg.Emit(OpCodes.Ldloca, result);
                                _ilg.Emit(OpCodes.Initobj, resultType);
                                _ilg.Emit(OpCodes.Ldloc, result);
                                FreeLocal(result);
                            }
                            else
                            {
                                _ilg.Emit(OpCodes.Ldnull);
                            }
                        }
                        else
                        {
                            switch (nodeType)
                            {
                                case ExpressionType.LessThan:
                                case ExpressionType.LessThanOrEqual:
                                case ExpressionType.GreaterThan:
                                case ExpressionType.GreaterThanOrEqual:
                                    _ilg.Emit(OpCodes.Ldc_I4_0);
                                    break;
                                default:
                                    throw Error.UnknownLiftType(nodeType);
                            }
                        }
                        _ilg.MarkLabel(exit);
                        return;
                    }
                case ExpressionType.Equal:
                case ExpressionType.NotEqual:
                    {
                        if (TypeUtils.AreEquivalent(resultType, TypeUtils.GetNullableType(mc.Type)))
                        {
                            goto default;
                        }
                        Label exit = _ilg.DefineLabel();
                        Label exitAllNull = _ilg.DefineLabel();
                        Label exitAnyNull = _ilg.DefineLabel();

                        LocalBuilder anyNull = _ilg.DeclareLocal(typeof(bool));
                        LocalBuilder allNull = _ilg.DeclareLocal(typeof(bool));
                        _ilg.Emit(OpCodes.Ldc_I4_0);
                        _ilg.Emit(OpCodes.Stloc, anyNull);
                        _ilg.Emit(OpCodes.Ldc_I4_1);
                        _ilg.Emit(OpCodes.Stloc, allNull);

                        for (int i = 0, n = paramList.Length; i < n; i++)
                        {
                            ParameterExpression v = paramList[i];
                            Expression arg = argList[i];
                            _scope.AddLocal(this, v);
                            if (TypeUtils.IsNullableType(arg.Type))
                            {
                                EmitAddress(arg, arg.Type);
                                _ilg.Emit(OpCodes.Dup);
                                _ilg.EmitHasValue(arg.Type);
                                _ilg.Emit(OpCodes.Ldc_I4_0);
                                _ilg.Emit(OpCodes.Ceq);
                                _ilg.Emit(OpCodes.Dup);
                                _ilg.Emit(OpCodes.Ldloc, anyNull);
                                _ilg.Emit(OpCodes.Or);
                                _ilg.Emit(OpCodes.Stloc, anyNull);
                                _ilg.Emit(OpCodes.Ldloc, allNull);
                                _ilg.Emit(OpCodes.And);
                                _ilg.Emit(OpCodes.Stloc, allNull);
                                _ilg.EmitGetValueOrDefault(arg.Type);
                            }
                            else
                            {
                                EmitExpression(arg);
                                if (!arg.Type.GetTypeInfo().IsValueType)
                                {
                                    _ilg.Emit(OpCodes.Dup);
                                    _ilg.Emit(OpCodes.Ldnull);
                                    _ilg.Emit(OpCodes.Ceq);
                                    _ilg.Emit(OpCodes.Dup);
                                    _ilg.Emit(OpCodes.Ldloc, anyNull);
                                    _ilg.Emit(OpCodes.Or);
                                    _ilg.Emit(OpCodes.Stloc, anyNull);
                                    _ilg.Emit(OpCodes.Ldloc, allNull);
                                    _ilg.Emit(OpCodes.And);
                                    _ilg.Emit(OpCodes.Stloc, allNull);
                                }
                                else
                                {
                                    _ilg.Emit(OpCodes.Ldc_I4_0);
                                    _ilg.Emit(OpCodes.Stloc, allNull);
                                }
                            }
                            _scope.EmitSet(v);
                        }
                        _ilg.Emit(OpCodes.Ldloc, allNull);
                        _ilg.Emit(OpCodes.Brtrue, exitAllNull);
                        _ilg.Emit(OpCodes.Ldloc, anyNull);
                        _ilg.Emit(OpCodes.Brtrue, exitAnyNull);

                        EmitMethodCallExpression(mc);
                        if (TypeUtils.IsNullableType(resultType) && !TypeUtils.AreEquivalent(resultType, mc.Type))
                        {
                            ConstructorInfo ci = resultType.GetConstructor(new Type[] { mc.Type });
                            _ilg.Emit(OpCodes.Newobj, ci);
                        }
                        _ilg.Emit(OpCodes.Br_S, exit);

                        _ilg.MarkLabel(exitAllNull);
                        _ilg.EmitBoolean(nodeType == ExpressionType.Equal);
                        _ilg.Emit(OpCodes.Br_S, exit);

                        _ilg.MarkLabel(exitAnyNull);
                        _ilg.EmitBoolean(nodeType == ExpressionType.NotEqual);

                        _ilg.MarkLabel(exit);
                        return;
                    }
            }
        }
コード例 #55
0
        static bool TryUncheckedCast(MethodCallExpression node, ref Expression rewrite)
        {
            MethodInfo info = node.Method;
            Type decType = info.DeclaringType;
            string name = info.Name;

            if (decType == typeof(RT))
            {
                switch (name)
                {
                    case "doubleCast":
                    case "uncheckedDoubleCast":
                    case "longCast":
                    case "uncheckedIntCast":
                    case "uncheckedLongCast":
                        {
                            ParameterInfo[] pinfos = info.GetParameters();
                            if (pinfos.Length == 1 && pinfos[0].ParameterType != typeof(object))
                            {
                                rewrite = Expression.Convert(node.Arguments[0], info.ReturnType);
                                return true;
                            }
                        }
                        break;
                    case "aget":
                        {
                            ParameterInfo[] pinfos = info.GetParameters();
                            if (pinfos.Length == 2 && pinfos[0].ParameterType.IsArray)
                            {
                                rewrite = Expression.ArrayIndex(node.Arguments[0], node.Arguments[1]);
                                return true;
                            }
                        }
                        break;

                    case "alength":
                        {
                            ParameterInfo[] pinfos = info.GetParameters();
                            if (pinfos.Length == 1 && pinfos[0].ParameterType.IsArray)
                            {
                                rewrite = Expression.ArrayLength(node.Arguments[0]);
                                return true;
                            }
                        }
                        break;
                }
            }
            else if (decType == typeof(Util))
            {
                if (name == "identical")
                {
                    ParameterExpression param1 = Expression.Parameter(typeof(Object), "temp1");
                    ParameterExpression param2 = Expression.Parameter(typeof(Object), "temp2");

                    rewrite = Expression.Block(typeof(bool), new ParameterExpression[] { param1, param2 },
                        Expression.Assign(param1, node.Arguments[0]),
                        Expression.Assign(param2, node.Arguments[1]),
                        Expression.Condition(
                            Expression.TypeIs(param1, typeof(ValueType)),
                            Expression.Call(param1, typeof(object).GetMethod("Equals", new Type[] { typeof(object) }), param2),
                            Expression.ReferenceEqual(param1, param2)));
                    return true;
                }
                else if (name == "equiv")
                {
                    ParameterInfo[] pinfos = info.GetParameters();
                    if (pinfos.Length == 2
                        && pinfos[0].ParameterType == pinfos[1].ParameterType
                        && (pinfos[0].ParameterType == typeof(long) || pinfos[0].ParameterType == typeof(double) || pinfos[0].ParameterType == typeof(bool)))
                    {
                        rewrite = Expression.Equal(node.Arguments[0], node.Arguments[1]);
                        return true;
                    }
                }
            }
            else if (decType == typeof(Numbers))
            {
                ParameterInfo[] pinfos = info.GetParameters();

                if (pinfos.Length == 1)
                {
                    Type t0 = pinfos[0].ParameterType;
                    Expression arg0 = node.Arguments[0];
                    if (t0 == typeof(double))
                    {
                        switch (name)
                        {
                            case "minus":
                            case "unchecked_minus":
                                rewrite = Expression.Negate(arg0);
                                return true;
                            case "inc":
                            case "unchecked_inc":
                                rewrite = Expression.Increment(arg0);
                                return true;
                            case "dec":
                            case "unchecked_dec":
                                rewrite = Expression.Decrement(arg0);
                                return true;
                            case "isZero":
                                rewrite = Expression.Equal(arg0, Expression.Constant(0.0));
                                return true;
                            case "isPos":
                                rewrite = Expression.GreaterThan(arg0, Expression.Constant(0.0));
                                return true;
                            case "isNeg":
                                rewrite = Expression.LessThan(arg0, Expression.Constant(0.0));
                                return true;
                        }
                    }
                    else if (t0 == typeof(long))
                    {
                        switch (name)
                        {
                            case "unchecked_minus":
                                rewrite = Expression.Negate(arg0);
                                return true;
                            case "unchecked_inc":
                                rewrite = Expression.Increment(arg0);
                                return true;
                            case "unchecked_dec":
                                rewrite = Expression.Decrement(arg0);
                                return true;
                            case "isZero":
                                rewrite = Expression.Equal(arg0, Expression.Constant(0L));
                                return true;
                            case "isPos":
                                rewrite = Expression.GreaterThan(arg0, Expression.Constant(0L));
                                return true;
                            case "isNeg":
                                rewrite = Expression.LessThan(arg0, Expression.Constant(0L));
                                return true;
                        }
                    }
                    else if (t0 == typeof(int))
                    {
                        switch (name)
                        {
                            case "unchecked_int_negate":
                                rewrite = Expression.Negate(arg0);
                                return true;
                            case "unchecked_int_inc":
                                rewrite = Expression.Increment(arg0);
                                return true;
                            case "unchecked_int_dec":
                                rewrite = Expression.Decrement(arg0);
                                return true;
                        }
                    }
                }
                else if (pinfos.Length == 2 && pinfos[0].ParameterType == pinfos[1].ParameterType)
                {
                    Type t0 = pinfos[0].ParameterType;
                    Expression arg0 = node.Arguments[0];
                    Expression arg1 = node.Arguments[1];
                    if (t0 == typeof(double))
                    {
                        switch (name)
                        {
                            case "add":
                            case "unchecked_add":
                                rewrite = Expression.Add(arg0, arg1);
                                return true;
                            case "multiply":
                            case "unchecked_multiply":
                                rewrite = Expression.Multiply(arg0, arg1);
                                return true;
                            case "divide":
                                rewrite = Expression.Divide(arg0, arg1);
                                return true;
                            case "minus":
                            case "unchecked_minus":
                                rewrite = Expression.Subtract(arg0, arg1);
                                return true;
                            case "lt":
                                rewrite = Expression.LessThan(arg0, arg1);
                                return true;
                            case "lte":
                                rewrite = Expression.LessThanOrEqual(arg0, arg1);
                                return true;
                            case "gt":
                                rewrite = Expression.GreaterThan(arg0, arg1);
                                return true;
                            case "gte":
                                rewrite = Expression.GreaterThanOrEqual(arg0, arg1);
                                return true;
                            case "equiv":
                                rewrite = Expression.Equal(arg0, arg1);
                                return true;
                        }
                    }
                    else if (t0 == typeof(long))
                    {
                        switch (name)
                        {
                            case "and":
                                rewrite = Expression.And(arg0, arg1);
                                return true;
                            case "or":
                                rewrite = Expression.Or(arg0, arg1);
                                return true;
                            case "xor":
                                rewrite = Expression.ExclusiveOr(arg0, arg1);
                                return true;

                            case "remainder":
                                rewrite = Expression.Modulo(arg0, arg1);
                                return true;
                            case "shiftLeft":
                                rewrite = Expression.LeftShift(arg0, Expression.Convert(arg1,typeof(int)));
                                return true;
                            case "shiftRight":
                                rewrite = Expression.RightShift(arg0, Expression.Convert(arg1,typeof(int)));
                                return true;
                            case "quotient":
                                rewrite = Expression.Divide(arg0, arg1);
                                return true;
                            case "unchecked_add":
                                rewrite = Expression.Add(arg0, arg1);
                                return true;
                            case "unchecked_minus":
                                rewrite = Expression.Subtract(arg0, arg1);
                                return true;
                            case "unchecked_multiply":
                                rewrite = Expression.Multiply(arg0, arg1);
                                return true;
                            case "lt":
                                rewrite = Expression.LessThan(arg0, arg1);
                                return true;
                            case "lte":
                                rewrite = Expression.LessThanOrEqual(arg0, arg1);
                                return true;
                            case "gt":
                                rewrite = Expression.GreaterThan(arg0, arg1);
                                return true;
                            case "gte":
                                rewrite = Expression.GreaterThanOrEqual(arg0, arg1);
                                return true;
                            case "equiv":
                                rewrite = Expression.Equal(arg0, arg1);
                                return true;
                        }
                    }
                    else if (t0 == typeof(int))
                    {
                        switch (name)
                        {
                            case "shiftLeftInt":
                                rewrite = Expression.LeftShift(arg0, arg1);
                                return true;
                            case "shiftRightInt":
                                rewrite = Expression.RightShift(arg0, arg1);
                                return true;
                            case "unchecked_int_add":
                                rewrite = Expression.Add(arg0, arg1);
                                return true;
                            case "unchecked_int_subtract":
                                rewrite = Expression.Subtract(arg0, arg1);
                                return true;
                            case "unchecked_int_multiply":
                                rewrite = Expression.Multiply(arg0, arg1);
                                return true;
                            case "unchecked_int_divide":
                                rewrite = Expression.Divide(arg0, arg1);
                                return true;
                            case "unchecked_int_remainder":
                                rewrite = Expression.Modulo(arg0, arg1);
                                return true;
                        }
                    }
                }
            }

            return false;
        }