2015-04-18 8 views
5

mir eine Linq-Abfrage mit einem select habe, von meinen Linq Abfrage-Provider es mir einen Ausdrucksbaum ein MethodCallExpression enthält, sondern nur, wie kann ich die select Projektionen vom MethodCallExpression bekommen?Erste Projektionen von Method

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 ... 

Abfrage aussehen kann:

var queryable = new MyQueriableClass(); 

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

Antwort

3

Es ist nicht genau klar ist, was Sie tun, aber

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

Die body am Ende sein sollte, was Sie wollen (oder vielleicht die lambda kurz vor dem Ende). Beachten Sie die Kommentare am Anfang des Codeblocks.

+0

Mit Ihrem Ansatz ist 'body' dann' ding.id == 1' in meinem Code, nicht die "Wort" -Projektion, auf die ich gehofft hatte. –

+0

@IngeHenriksen Ich habe gerade einen Kommentar hinzugefügt ... * Die Abfrage 'von Wort in Worten wo Wort.Länge> 0 Wort auswählen 'hat keine Auswahl auch * (so eindeutig nicht deins) ... Wenn Sie Verwenden Sie die funktionale Notation, es wird klar warum: 'query.Where (word => word.Length> 0)' wo ist das 'Select' hier? da ist nicht! – xanatos

+0

Ich habe mein Beispiel aktualisiert, vielleicht ist es jetzt klarer? –