Aufrufen einer generischen Methode mit Lambda-Ausdrücken (und einem Typ, der nur zur Laufzeit bekannt ist)

c# expression expression-trees generics lambda

Frage

Sie können Lambda-Ausdrucksobjekte verwenden , um ein Lambda als Ausdruck darzustellen.

Wie erstellen Sie ein Lambda-Ausdrucksobjekt, das einen generischen Methodenaufruf darstellt, wenn Sie nur den Typ kennen, den Sie für die generische Methodensignatur zur Laufzeit verwenden?

Beispielsweise:

Ich möchte ein Lambda-Ausdrucksobjekt erstellen, das aufgerufen werden soll: public static TSource Last<TSource>( this IEnumerable<TSource> source )

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

Akzeptierte Antwort

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 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)
}

Beliebte Antwort

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

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

Der Code im Beispiel von dtb ist ziemlich genau das Gleiche, was der C # -Compiler automatisch für Sie aus diesem Lambda-Ausdruck generiert (kompiliert als Ausdrucksbaum, weil der Rückgabetyp Expression ).

Wenn Sie den Typ zur Laufzeit kennen, können Sie entweder die Lösung von dtb verwenden oder Sie können die CreateLambda Methode (oben) mithilfe von Reflection aufrufen, die möglicherweise langsamer ist, aber den Code in das Lambda im natürlichen C # schreiben kann:

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

Das CreateLambda an diesem Ansatz ist, dass der Code in CreateLambda sehr viel komplizierter sein kann, was unter Verwendung von Ausdrucksbäumen sehr schwierig wäre.




Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum