2015-04-18 14 views
5

ho una query LINQ con un select, dal mio fornitore di query LINQ io ottenere un albero espressione contenente un MethodCallExpression, ma proprio come posso ottenere i selezionare proiezioni dalla MethodCallExpression?Come proiezioni da 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 ... 

query potrebbe sembrare:

var queryable = new MyQueriableClass(); 

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

risposta

3

Non è esattamente chiaro cosa si sta facendo, ma

// 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; 
    } 
} 

Il body alla fine dovrebbe essere quello che vuoi (o forse lo lambda poco prima della fine). Prendere nota dei commenti all'inizio del blocco di codice.

+0

Utilizzando il tuo approccio, quindi 'body' è' thing.id == 1' nel mio codice, non la proiezione di "parola" che speravo. –

+0

@IngeHenriksen Stavo solo aggiungendo un commento ... * La query 'da parole in parole dove word.Length> 0 select word' non ha una selezione troppo * (quindi chiaramente non la tua) ... Se tu usa la notazione funzionale, sarà chiaro il motivo: 'query.Where (word => word.Length> 0)' dov'è il 'Select' qui? non c'è! – xanatos

+0

Ho aggiornato il mio esempio, forse ora è più chiaro? –

Problemi correlati