2010-05-17 10 views
9

Sie können Lambda Expression Objects verwenden, um ein Lambda als Ausdruck darzustellen.Aufrufen einer generischen Methode mit Lambda Expressions (und einem Typ, der nur zur Laufzeit bekannt ist)

Wie erstellen Sie einen Lambda Expression Object, der einen generischen Methodenaufruf repräsentiert, wenn Sie nur den Typ kennen, den Sie für die generische Methodensignatur zur Laufzeit verwenden?

Zum Beispiel:

Ich möchte ein Lambda Expression Objects anrufen erstellen: public static TSource Last<TSource>(this IEnumerable<TSource> source)

Aber ich weiß nur, was TSource zur Laufzeit ist.

+0

Dies ist nicht ganz klar. Welche Methode für welches Objekt möchten Sie erstellen? Möchten Sie einen Verweis auf die letzte generische Methode mit einem Lambda-Ausdruck? – casperOne

+0

@CasperOne: Hallo Casper! a) Ich versuche eine Instanz von ** TheObject ** zu erstellen, die auf ** TheMethod ** verweist. b) Ja, ich möchte die letzte Methode mit einem Lambda-Ausdruck referenzieren (Lambda-Ausdruck-Objekt meine ich). Danke:) – SDReyes

Antwort

20
static Expression<Func<IEnumerable<T>, T>> CreateLambda<T>() 
{ 
    var source = Expression.Parameter(
     typeof(IEnumerable<T>), "source"); 

    var call = Expression.Call(
     typeof(Enumerable), "Last", new Type[] { typeof(T) }, source); 

    return Expression.Lambda<Func<IEnumerable<T>, T>>(call, source) 
} 

oder

static LambdaExpression CreateLambda(Type type) 
{ 
    var source = Expression.Parameter(
     typeof(IEnumerable<>).MakeGenericType(type), "source"); 

    var call = Expression.Call(
     typeof(Enumerable), "Last", new Type[] { type }, source); 

    return Expression.Lambda(call, source) 
} 
2

Ich verstehe nicht ganz die Frage, aber der Code, der geschrieben werden DTB schrieb könnte einfach als:

class MyUtils { 
    public static Expression<Func<IEnumerable<T>, T>> CreateLambda<T>() { 
    return source => source.Last(); 
    } 
} 

Der Code in der Probe durch dtb ist fast genau das gleiche, was der C# -Compiler automatisch für Sie aus diesem Lambda-Ausdruck generiert (kompiliert als Ausdrucksbaum, weil der Rückgabetyp Expression ist).

Wenn Sie den Typ zur Laufzeit kennen, dann können Sie entweder die Lösung von dtb verwenden, oder Sie können die CreateLambda Methode (siehe oben) mit Reflexion aufrufen, die langsamer sein, aber können Sie den Code in das Lambda zu schreiben, in die natürliche C#:

var createMeth = typeof(MyUtils).GetMethod("CreateLambda"); 
LambdaExpression l = createMeth.MakeGenericMethod(yourType).Invoke(); 

das schöne an diesem Ansatz ist, dass der Code in CreateLambda komplizierter viel sein kann, was wirklich schwer explizit Bäume zu tun mit Ausdruck wäre.

+0

Hallo Tomas! Ich muss meine Programmierkommunikationsfähigkeiten verbessern Ich weiß, ich weiß hahahha (aber mach dir keine Sorgen, ich arbeite daran:). Ich habe die Frage aktualisiert, um darzustellen, was ich wirklich meinte. Netter Refactor! +1 – SDReyes

+0

@SDReyes: "zur Laufzeit" war der wichtige Punkt. Sie können trotzdem die nette C# -Syntax dafür verwenden (ohne explizit Ausdrucksbäume zu konstruieren). Siehe meine aktualisierte Antwort. –

+0

Hallo Tomas!, Ich stimme dir zu. Mit diesem Ansatz können Sie einfach komplexe Lambdas innerhalb der CreateLambda-Methode implementieren (mit nur einem Performance-Kompromiss). Ich werde dieses Mal den dtb-Ansatz verwenden, da wir bereits viele Ausdrücke in der Komponente verwenden, an der wir gerade arbeiten, und ich möchte die Kohärenz zwischen dem Code bewahren:). aber ich werde mich freuen, auch in den nächsten Szenarien deine zu implementieren! Netter Job Tomas! Grüße. SD – SDReyes

Verwandte Themen