Exemple #1
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            if (node.HasArgImplementing(typeof(IQueryable)))
            {
                var newArgs = node.Arguments.Select(a => StripQuotes(base.Visit(a))).ToArray();

                // TODO: This is an imperfect shortcut to find an Enumerable
                // method that corresponds to the given Queryable method.
                // Should work for most (if not all) LINQ operators, though,
                // which is primarily what we are after.  To do this
                // "correctly", i.e., the same as what the compiler does,
                // we'd need to effectively reproduce extension method lookup,
                // generic overload resolution, etc.  This is not trivial.
                var newMethod = typeof(Enumerable).GetMethods().FirstOrDefault(
                    m => m.Name == node.Method.Name &&
                    newArgs.Length == m.GetParameters().Length &&
                    newArgs.Zip(m.GetParameters().Select(p => p.ParameterType),
                                (arg, type) => arg.Type.Implements(type.GetGenericTypeDefinition())).All(b => b == true));

                if (newMethod == null)
                {
                    throw new Exception("Couldn't find IEnumerable<> replacement for method " + node.Method.Name);
                }

                if (newMethod.IsGenericMethod)
                {
                    newMethod = newMethod.MakeGenericMethod(node.Method.GetGenericArguments().Select(
                                                                t => t.Implements(typeof(IQueryable <>)) ?
                                                                typeof(IEnumerable <>).MakeGenericType(t.GetGenericArguments()[0])
                        : t).ToArray());
                }

                return(Expression.Call(newMethod, newArgs));
            }
            else
            {
                return(base.VisitMethodCall(node));
            }
        }