2010-05-17 3 views
9

Vous pouvez utiliser Lambda Expression Objects pour représenter un lambda en tant qu'expression.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)

Comment créer un Lambda Expression Object représentant un appel de méthode générique, si vous connaissez seulement le type -que vous utilisez pour la signature de méthode générique- au moment de l'exécution?

Par exemple:

Je veux créer un Lambda Expression Objects pour appeler: public static TSource Last<TSource>(this IEnumerable<TSource> source)

Mais je ne sais ce que TSource est en cours d'exécution.

+0

Ce n'est pas tout à fait clair. Quelle méthode sur quel objet essayez-vous de créer? Voulez-vous une référence à la dernière méthode générique avec une expression lambda? – casperOne

+0

@CasperOne: Salut Casper! a) J'essaye de créer une instance de ** TheObject **, qui fait référence à ** TheMethod **. b) oui, je veux référencer la dernière méthode avec une expression lambda (objet d'expression lambda que je veux dire). Merci:) – SDReyes

Répondre

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

ou

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

Je ne comprends pas bien la question, mais le code qui DTB écrit pourrait être écrit simplement:

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

Le code dans l'échantillon par DTB est à peu près la même chose que ce que le compilateur C# génère automatiquement pour vous à partir de cette expression lambda (compilé comme arbre d'expression, car le type de retour est Expression). Si vous connaissez le type lors de l'exécution, vous pouvez utiliser la solution par dtb ou vous pouvez appeler la méthode CreateLambda (ci-dessus) en utilisant Reflection, qui peut être plus lente, mais vous permet d'écrire le code dans le lambda dans le naturel C#:

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

la bonne chose au sujet de cette approche est que le code CreateLambda peut être beaucoup plus compliqué, ce qui serait vraiment difficile à faire en utilisant des arbres d'expression explicitement.

+0

Salut Tomas! J'ai besoin d'améliorer mes compétences en communication de programmation, je sais, je sais hahahha (mais ne vous inquiétez pas je travaille dessus:). J'ai mis à jour la question pour représenter ce que je voulais vraiment dire. Beau refactor! +1 – SDReyes

+0

@SDReyes: "à l'exécution" était le point important. Vous pouvez toujours utiliser la belle syntaxe C# pour cela (sans explicitement construire des arbres d'expression). Voir ma réponse mise à jour. –

+0

Salut Tomas !, je suis d'accord avec vous. cette approche vous permet d'implémenter facilement des lambdas complexes dans la méthode CreateLambda (avec juste un compromis de performance). Je vais utiliser l'approche dtb cette fois, car nous utilisons déjà beaucoup d'expressions dans le composant sur lequel nous travaillons, et je veux garder une cohérence entre le code:). mais je vais être heureux de mettre en œuvre le vôtre dans les prochains scénarios aussi! Beau travail Tomas! Cordialement. Dakota du Sud – SDReyes

Questions connexes