2015-04-18 2 views
5

У меня есть запрос Linq с select, от моего провайдера Linq запросов это я получаю дерево выражения содержащий MethodCallExpression, но только, как я могу получить выберите проекции из MethodCallExpression?Получение проекции от MethodCallExpression

internal static object Execute(Expression expression, bool isEnumerable) 
    { 
     var whereExpression = expression as MethodCallExpression; 
     if (whereExpression == null) throw new InvalidProgramException("Error"); 

     foreach (var arg in whereExpression.Arguments) 
     { 
      if (arg is UnaryExpression) 
      { 
       var unaryExpression = arg as UnaryExpression; 

       var lambdaExpression = unaryExpression.Operand as LambdaExpression; 
       if (lambdaExpression == null) continue; 

       // Here I would like to get the select projections, in this example the "word" projection ... 

запрос может выглядеть следующим образом:

var queryable = new MyQueriableClass(); 

var query = from thing in queryable 
      where thing.id == 1 
      select word; 

ответ

3

Это не совсем понятно, что вы делаете, но

// note the AsQueryable! Otherwise there is no 
// Expression tree! 
var words = new List<string>() { "an", "apple", "a", "day" }.AsQueryable(); 

// Note that even IQueryable<string> query = words; 
// is a perfectly good query without a projection! 
// The query 
// from word in words where word.Length > 0 select word 
// doesn't have a select too (try looking at the 
// expression tree... The select has been elided) 
// The projection if not present is implicit, the 
// whole object. 
var query = from word in words 
      select word; 

var exp = query.Expression; 
var methodCallExpression = exp as MethodCallExpression; 

if (methodCallExpression != null) 
{ 
    MethodInfo method = methodCallExpression.Method; 

    if (method.DeclaringType == typeof(Queryable) && method.Name == "Select") 
    { 
     var source = methodCallExpression.Arguments[0]; 
     var selector = methodCallExpression.Arguments[1]; 

     // The selector parameter passed to Select is an 
     // Expression.Quote(subexpression), 
     // where subexpression is the lambda expression 
     // word => word here 
     if (selector.NodeType != ExpressionType.Quote) 
     { 
      throw new NotSupportedException(); 
     } 

     UnaryExpression unary = (UnaryExpression)selector; 
     Expression operand = unary.Operand; 

     if (operand.NodeType != ExpressionType.Lambda) 
     { 
      throw new NotSupportedException(); 
     } 

     LambdaExpression lambda = (LambdaExpression)operand; 

     // This is the "thing" that returns the result 
     Expression body = lambda.Body; 
    } 
} 

body в конце должно быть то, что вы хотите (или, возможно, lambda незадолго до конца). Обратите внимание на комментарии в начале кода.

+0

Используя ваш подход, 'body' является' thing.id == 1' в моем коде, а не «словом» проекции, на который я надеялся. –

+0

@IngeHenriksen Я просто добавлял комментарий ... * Запрос 'от слова в словах, где word.Length> 0 select word' не имеет выбора слишком * (так ясно не ваш) ... Если вы используйте функциональную нотацию, будет понятно, почему: 'query.Where (word => word.Length> 0)' где 'Select' здесь? нет! – xanatos

+0

Я обновил свой пример, возможно, теперь он яснее? –

Смежные вопросы