Appel d'une méthode générique à l'aide d'expressions Lambda (et d'un type uniquement connu au moment de l'exécution)

c# expression expression-trees generics lambda

Question

Vous pouvez utiliser des objets d'expression Lambda pour représenter un lambda en tant qu'expression.

Comment créer un objet d'expression Lambda représentant un appel de méthode générique, si vous connaissez uniquement le type que vous utilisez pour la signature de méthode générique au moment de l'exécution

Par exemple:

Je souhaite créer un objet d'expression Lambda à appeler: public static TSource Last<TSource>( this IEnumerable<TSource> source )

Mais je sais seulement ce qu'est TSource au moment de l'exécution.

Réponse acceptée

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

ou

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

Réponse populaire

Je ne comprends pas bien la question, mais le code écrit par dtb pourrait simplement être écrit ainsi:

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

Le code dans l'exemple de dtb est à peu près identique à ce que le compilateur C # génère automatiquement pour vous à partir de cette expression lambda (compilée sous forme d'arborescence d'expression, car le type de retour est Expression ).

Si vous connaissez le type au moment de l'exécution, vous pouvez utiliser la solution avec dtb ou appeler la méthode CreateLambda (ci-dessus) à l'aide de Reflection, ce qui peut être plus lent, mais vous permet d'écrire le code dans le lambda dans le C # naturel:

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

La bonne chose à propos de cette approche est que le code dans CreateLambda peut être beaucoup plus compliqué, ce qui serait très difficile à faire en utilisant explicitement des arbres d'expression.




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi