2016-05-14 7 views
3

Ich bin auf der Suche nach einem Ausdrucksbaum zur Laufzeit dynamisch erstellen. Der Ausdruck ruft mehrere Methoden auf und übergibt das Ergebnis einer Methode an die nächste, wobei die letzte Methode etwas zurückgibt. Ich kann einzelne Methodenaufrufausdrücke ohne Schwierigkeiten erstellen und ausführen, kann aber nicht herausfinden, wie diese Methoden in einem Ausdruck miteinander verknüpft werden.Verkettung Methode ruft in Expression Tree zur Laufzeit

Vereinfachter Code unten. Der Live-Code hat Methoden mit variabler Anzahl von Methodenaufrufen und Parametern.

Konzeptionell Ich versuche, das entspricht dies zur Laufzeit zu erhalten, indem die Kombination von expression1 & expression2

var uncompileable = HostNumber.GetHostNumber("Bleacher").HostStatus.GetHostStatus(); // Status = "Online" 

using System; 
using System.Linq.Expressions; 

namespace SO 
{ 
    internal class Program 
    { 
     private static void Main(string[] args) 
     { 
      ConstantExpression param1 = Expression.Constant(Convert.ChangeType("Bleacher", typeof(String)));  
      MethodCallExpression expression1 = Expression.Call(typeof(HostNumber), "GetHostNumber", null, new Expression[] { param1 }); 

      ConstantExpression param2 = Expression.Constant(Convert.ChangeType("45", typeof(int))); 
      MethodCallExpression expression2 = Expression.Call(typeof(HostStatus), "GetHostStatus", null, new Expression[] { param2 }); 

      var invokee = Expression.Lambda(expression1).Compile(); 
      var result = invokee.DynamicInvoke(); 

     } 
    } 

    public class HostNumber 
    { 
     public static int GetHostNumber(string hostName) 
     { 
      return 45; 
     } 
    } 

    public static class HostStatus 
    { 
     public static string GetHostStatus(int hostNumber) 
     { 
      return "Online"; 
     } 
    } 
} 
+0

'HostNumber.GetHostNumber (" Bleacher "). HostStatus.GetHostStatus()' kompiliert nicht, da 'GetHostNumber' eine ganze Zahl zurückgibt, nicht irgendein Objekt, das eine' HostStatus' Eigenschaft hat. –

+0

Ich weiß. Ich habe gerade diese Zeile hinzugefügt, um das Konzept dessen zu zeigen, was ich zu erreichen versuche. Die Ausgabe von HostNumber.GetHostNumber ("Bleacher") (45) sollte dann an HostStatus.GetHostStatus() übergeben werden. Danke – Canacourse

Antwort

1

Hier ist, wie Sie es tun würde:

var expression = 
    Expression.Call(
     typeof (HostStatus).GetMethod("GetHostStatus", BindingFlags.Public | BindingFlags.Static), 
     Expression.Call(
      typeof (HostNumber).GetMethod("GetHostNumber", BindingFlags.Public | BindingFlags.Static), 
      Expression.Constant("Bleacher", typeof (string)))); 

var func = Expression.Lambda<Func<string>>(expression).Compile(); 

var result = func(); 

Übrigens ist mir nicht klar, warum machst du das? Warum erstellen Sie einen statischen Ausdruck und kompilieren ihn dann?

+0

Das funktioniert dank. Diese Methodenaufrufe werden von einer Konfigurationsdatei (DSL) analysiert. – Canacourse

+0

Sie sind willkommen. Aha. Es ist also dynamisch, weil die Methodennamen nicht statisch sind. –

+0

Ja genau, aber der Ausdruck kann einen Methodenaufruf oder bis zu drei enthalten, und die Methodenaufrufe haben möglicherweise keine Parameter oder bis zu zwei. Ihr Code könnte also kompliziert werden. Ich hatte versucht, Ausdruck Besucher zu verwenden, um die Ausdrücke zusammenzuführen, aber auf dem Weg verloren. – Canacourse