Beispiel #1
0
        public void Bind()
        {
            Expression <Func <IEnumerable <object>, int> > e1 = x => 0;

            var method = ExpressionMethodBinder.Bind(typeof(Source), "Test2", null, new Expression[] { Expression.Constant(e1), Expression.Constant(1) });

            Assert.NotNull(method);
        }
Beispiel #2
0
        public void SelectManyBind()
        {
            PetOwner[] petOwners =
            { new PetOwner         {
                  Name = "Higa",
                  Pets = new List <string> {
                      "Scruffy", "Sam"
                  }
              },
              new PetOwner {
                  Name = "Ashkenazi",
                  Pets = new List <string> {
                      "Walker", "Sugar"
                  }
              },
              new PetOwner {
                  Name = "Price",
                  Pets = new List <string> {
                      "Scratches", "Diesel"
                  }
              },
              new PetOwner {
                  Name = "Hines",
                  Pets = new List <string> {
                      "Dusty"
                  }
              } };

            Expression <Func <PetOwner, List <string> > > e2 = petOwner => petOwner.Pets;
            Expression <Func <PetOwner, string, string> > e3 = (petOwner, petName) => petName + petOwner;

            var method = ExpressionMethodBinder.Bind(typeof(Enumerable), "SelectMany", null, new Expression[]
            {
                Expression.Constant(petOwners), e2, e3
            });

            Assert.NotNull(method);
        }
Beispiel #3
0
        private Expression VisitMethodCall(ODataMethodCallExpression node)
        {
            var functionName = node.MethodName.ToLowerInvariant();

            switch (functionName)
            {
            case "contains":
            {
                var right = Visit(node.Arguments[0]);
                var left  = Visit(node.Arguments[1]);

                return(Expression.Call(right, MethodProvider.ContainsMethod, new[] { left }));
            }

            case "endswith":
            {
                var right = Visit(node.Arguments[1]);
                var left  = Visit(node.Arguments[0]);

                return(Expression.Call(left, MethodProvider.EndsWithMethod, new[] { right }));
            }

            case "startswith":
            {
                var right = Visit(node.Arguments[1]);
                var left  = Visit(node.Arguments[0]);

                return(Expression.Call(left, MethodProvider.StartsWithMethod, new[] { right }));
            }

            case "length":
            {
                var left = Visit(node.Arguments[0]);

                return(Expression.Property(left, MethodProvider.LengthProperty));
            }

            case "indexof":
            {
                var right = Visit(node.Arguments[1]);
                var left  = Visit(node.Arguments[0]);

                return(Expression.Call(left, MethodProvider.IndexOfMethod, new[] { right }));
            }

            case "substring":
            {
                if (node.Arguments.Length == 3)
                {
                    return(Expression.Call(Visit(node.Arguments[0]), MethodProvider.SubstringMethodWithTwoArg, new[] { Visit(node.Arguments[1]), Visit(node.Arguments[2]) }));
                }

                if (node.Arguments.Length == 2)
                {
                    return(Expression.Call(Visit(node.Arguments[0]), MethodProvider.SubstringMethodWithOneArg, new[] { Visit(node.Arguments[1]) }));
                }

                throw new NotSupportedException();        //Нет перегрузки для данного метода
            }

            case "tolower":
            {
                var left = Visit(node.Arguments[0]);

                return(Expression.Call(left, MethodProvider.ToLowerMethod));
            }

            case "toupper":
            {
                var left = Visit(node.Arguments[0]);

                return(Expression.Call(left, MethodProvider.ToUpperMethod));
            }

            case "trim":
            {
                var left = Visit(node.Arguments[0]);

                return(Expression.Call(left, MethodProvider.TrimMethod));
            }

            case "hour":
            {
                var left = Visit(node.Arguments[0]);

                if (left.Type.IsNullableType())
                {
                    left = Expression.Property(left, "Value");
                }

                return(Expression.Property(left, MethodProvider.HourProperty));
            }

            case "minute":
            {
                var left = Visit(node.Arguments[0]);

                if (left.Type.IsNullableType())
                {
                    left = Expression.Property(left, "Value");
                }

                return(Expression.Property(left, MethodProvider.MinuteProperty));
            }

            case "second":
            {
                var left = Visit(node.Arguments[0]);

                if (left.Type.IsNullableType())
                {
                    left = Expression.Property(left, "Value");
                }

                return(Expression.Property(left, MethodProvider.SecondProperty));
            }

            case "day":
            {
                var left = Visit(node.Arguments[0]);

                if (left.Type.IsNullableType())
                {
                    left = Expression.Property(left, "Value");
                }

                return(Expression.Property(left, MethodProvider.DayProperty));
            }

            case "month":
            {
                var left = Visit(node.Arguments[0]);

                if (left.Type.IsNullableType())
                {
                    left = Expression.Property(left, "Value");
                }

                return(Expression.Property(left, MethodProvider.MonthProperty));
            }

            case "year":
            {
                var left = Visit(node.Arguments[0]);

                if (left.Type.IsNullableType())
                {
                    left = Expression.Property(left, "Value");
                }

                return(Expression.Property(left, MethodProvider.YearProperty));
            }

            case "round":
            {
                var left = Visit(node.Arguments[0]);

                if (left.Type.IsNullableType())
                {
                    left = Expression.Property(left, "Value");
                }

                return(Expression.Call(left.Type == typeof(double) ? MethodProvider.DoubleRoundMethod : MethodProvider.DecimalRoundMethod, new[] { left }));
            }

            case "floor":
            {
                var left = Visit(node.Arguments[0]);

                if (left.Type.IsNullableType())
                {
                    left = Expression.Property(left, "Value");
                }

                return(Expression.Call(left.Type == typeof(double) ? MethodProvider.DoubleFloorMethod : MethodProvider.DecimalFloorMethod, new[] { left }));
            }

            case "ceiling":
            {
                var left = Visit(node.Arguments[0]);

                if (left.Type.IsNullableType())
                {
                    left = Expression.Property(left, "Value");
                }

                return(Expression.Call(left.Type == typeof(double) ? MethodProvider.DoubleCeilingMethod : MethodProvider.DecimalCeilingMethod, new[] { left }));
            }

            case "concat":
            {
                var right = Visit(node.Arguments[1]);
                var left  = Visit(node.Arguments[0]);

                return(Expression.Add(left, right, MethodProvider.ConcatMethod));
            }

            case "replace":
            {
                return(Expression.Call(Visit(node.Arguments[0]), MethodProvider.ReplaceMethod, new[] { Visit(node.Arguments[1]), Visit(node.Arguments[2]) }));
            }

            case "sum":
            case "average":
            {
                var context = Visit(node.Context);

                var genericArguments = context.Type.GetTypeGenericArguments();

                var arguments = node.Arguments.Select(argument => argument.NodeType == ExpressionType.Lambda ? VisitLambda((ODataLambdaExpression)argument, genericArguments[0]) : Visit(argument)).ToList();

                arguments.Insert(0, context);

                var type = context.Type.IsIQueryable() ? typeof(Queryable) : typeof(Enumerable);

                return(Expression.Call(type, functionName, arguments.Count == 1 ? Type.EmptyTypes : genericArguments, arguments.ToArray()));
            }

            case "min":
            case "max":
            case "selectmany":
            {
                var context = Visit(node.Context);

                var genericArguments = context.Type.GetGenericArguments();

                var arguments = node.Arguments.Select(argument => argument.NodeType == ExpressionType.Lambda ? VisitLambda((ODataLambdaExpression)argument, genericArguments[0]) : Visit(argument)).ToList();

                arguments.Insert(0, context);

                var type = context.Type.IsIQueryable() ? typeof(Queryable) : typeof(Enumerable);

                var expr = ExpressionMethodBinder.Bind(type, functionName, null, arguments.ToArray());

                return(expr);
            }

            case "groupby":
            case "orderby":
            case "orderbydescending":
            case "thenby":
            case "thenbydescending":
            case "select":
            {
                var context = Visit(node.Context);

                var genericArguments = context.Type.GetTypeGenericArguments().ToList();

                var lambda = (LambdaExpression)VisitLambda((ODataLambdaExpression)node.Arguments[0], genericArguments[0]);

                genericArguments.Add(lambda.ReturnType);

                var type = context.Type.IsIQueryable() ? typeof(Queryable) : typeof(Enumerable);

                return(Expression.Call(type, functionName, genericArguments.ToArray(), new[] { context, lambda }));
            }

            case "any":
            case "all":
            case "first":
            case "where":
            case "take":
            case "skip":
            case "distinct":
            case "last":
            case "lastordefault":
            case "single":
            case "singleordefault":
            case "defaultifempty":
            case "count":
            case "longcount":
            case "firstordefault":
            {
                var context = Visit(node.Context);

                var genericArguments = context.Type.GetTypeGenericArguments();

                var arguments = node.Arguments.Select(argument => argument.NodeType == ExpressionType.Lambda ? VisitLambda((ODataLambdaExpression)argument, genericArguments[0]) : Visit(argument)).ToList();

                arguments.Insert(0, context);

                var type = context.Type.IsIQueryable() ? typeof(Queryable) : typeof(Enumerable);

                return(Expression.Call(type, functionName, genericArguments, arguments.ToArray()));
            }

            case "isof":
            {
                //ParameterExpression parameter = null;
                Expression genericParameter = null;
                object     typeName         = null;
                if (node.Arguments.Length == 1)
                {
                    genericParameter = _parameters.Select(x => x.Value).FirstOrDefault();
                    typeName         = ((ConstantExpression)Visit(node.Arguments[0])).Value;
                }

                if (node.Arguments.Length == 2)
                {
                    var arguments = node.Arguments.Select(Visit).ToArray();
                    genericParameter = arguments[0];
                    typeName         = ((ConstantExpression)arguments[1]).Value;
                }

                if (genericParameter != null)
                {
                    var type = typeName is Type ? (Type)typeName : null;
                    if (type == null && KnownAssembly != null)
                    {
                        type = KnownAssembly.GetType((string)typeName);
                    }
                    return(Expression.TypeIs(genericParameter, type));
                }


                throw new NotSupportedException(node.DebugView());
            }

            case "cast":
            {
                if (node.Arguments.Length == 1)
                {
                    var parameter = _parameters.Select(x => x.Value).FirstOrDefault();
                    if (parameter != null)
                    {
                        var type = (Type)((ConstantExpression)Visit(node.Arguments[0])).Value;

                        return(Expression.TypeAs(parameter, type));
                    }
                }

                if (node.Arguments.Length == 2)
                {
                    var arguments = node.Arguments.Select(Visit).ToArray();

                    return(Expression.TypeAs(arguments[0], (Type)((ConstantExpression)arguments[1]).Value));
                }

                throw new NotSupportedException(node.DebugView());
            }

            case "substringof":
            {
                var right = Visit(node.Arguments[1]);
                var left  = Visit(node.Arguments[0]);

                return(Expression.Call(right, MethodProvider.ContainsMethod, new[] { left }));
            }

            default:
            {
                if (node.Context != null)
                {
                    var context = Visit(node.Context);

                    var arguments = node.Arguments.Select(Visit).ToList();

                    var expr = ExpressionMethodBinder.Bind(context.Type, functionName, context, arguments.ToArray());

                    if (expr == null)
                    {
                        throw new Exception(String.Format("Can't find a method: {0}", node.DebugView()));
                    }

                    return(expr);
                }

                if (MethodProvider.UserFunctions.ContainsKey(node.MethodName))
                {
                    var arguments = node.Arguments.Select(Visit).ToArray();

                    var methodExpression = ExpressionMethodBinder.Bind(
                        MethodProvider.UserFunctions[node.MethodName], node.MethodName, null, arguments);

                    if (methodExpression == null)
                    {
                        throw new Exception(String.Format("Can't find a method: {0}", node.DebugView()));
                    }

                    return(methodExpression);
                }

                throw new NotSupportedException(String.Format("Can't find a method: {0}", node.DebugView()));
            }
            }
        }