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