You must pass an argument as ConstantExpression :
private static void TestMethodCallCompilation() { var methodInfo = typeof(Program).GetMethod("GimmeExpression", BindingFlags.NonPublic | BindingFlags.Static); var lambdaExpression = Expression.Lambda<Func<bool>>(Expression.Constant(true)); var methodCallExpression = Expression.Call(null, methodInfo, Expression.Constant(lambdaExpression)); var wrapperLambda = Expression.Lambda(methodCallExpression); wrapperLambda.Compile().DynamicInvoke(); } private static void GimmeExpression(Expression<Func<bool>> exp) { Console.WriteLine(exp.GetType()); Console.WriteLine("Compiling and executing expression..."); Console.WriteLine(exp.Compile().Invoke()); }
The reason should be pretty obvious - you are passing a constant value, so it should be ConstantExpression . By passing this expression directly, you explicitly say "and get the exp value from this complex expression tree." And since this expression tree does not actually return Expression<Func<bool>> , you get an error message.
How IQueryable works, in fact it has no special relation. Extension methods on IQueryable should store all information about expressions - including the types and references of ParameterExpression and the like. That’s because they don’t actually do anything - they just build an expression tree. The real work happens when you call queryable.Provider.Execute(expression) . In principle, this is how polymorphism persists, even if we perform composition rather than inheritance (/ implementation of an interface). But this means that the IQueryable extension methods themselves cannot make any shortcuts - they do not know anything about how IQueryProvider will actually interpret the query, so they cannot throw anything away.
The most important benefit you get from this is that you can compose queries and subqueries. Consider the following query:
from item in dataSource where item.SomeRelatedItem.Where(subItem => subItem.SomeValue == 42).Count() > 2 select item;
Now it is translated something like this:
dataSource.Where(item => item.SomeRelatedItem.Where(subItem => subItem.SomeValue == 42).Count() > 2);
The external query is pretty obvious - we get Where with the given predicate. The internal query, however, will actually Call before Where , taking the actual predicate as an argument.
After making sure that the actual Where method calls are actually translated into the Where method Calls, both of these cases become the same, and your LINQProvider is that one bit is simpler :)
I actually wrote LINQ providers that do not implement IQueryable , and which do have some useful logic in methods like Where . This is much simpler and more efficient, but it has the drawback described above - the only way to handle subqueries is to manually Invoke Call expressions to get a "real" predicate expression. Yikes is pretty overhead for a simple LINQ query!
And of course, this helps you compile the various requested providers, although I have not actually seen (m) any examples of using two completely different providers in the same request.
As for the difference between Expression.Constant and Expression.Quote , they seem pretty similar. The most important difference is that Expression.Constant will treat any closures as actual constants, not closures. Expression.Quote , on the other hand, will preserve closure closures. What for? Since the closure objects themselves are also passed as Expression.Constant :) And since IQueryable trees make lambdas lambdas lambdas from [...], you really do not want to lose closure semantics at any point.