2010-05-17 9 views
9

Można użyć wartości Lambda Expression Objects do reprezentacji lambda jako wyrażenia.Wywołanie metody ogólnej za pomocą wyrażeń Lambda (i typu znanego tylko w środowisku wykonawczym)

Jak utworzyć Lambda Expression Object reprezentujący ogólne wywołanie metody, jeśli znany jest tylko typ, którego używa się do podpisu metody ogólnej w czasie wykonywania?

Na przykład:

Chcę utworzyć Lambda Expression Objects zadzwonić: public static TSource Last<TSource>(this IEnumerable<TSource> source)

Ale wiem tylko co TSource jest przy starcie.

+0

Nie jest to całkowicie jasne. Którą metodę obiektu chcesz utworzyć? Czy chcesz odwołać się do ostatniej ogólnej metody z wyrażeniem lambda? – casperOne

+0

@CasperOne: Cześć Casper! a) Próbuję utworzyć instancję klasy ** TheObject **, która odwołuje się do ** TheMethod **. b) tak, chcę odwołać się do ostatniej metody z wyrażeniem lambda (chodzi mi o obiekt wyrażenia lambda). Dzięki:) – SDReyes

Odpowiedz

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

lub

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

ja nie do końca rozumiem pytanie, ale kod, który napisał DTB może być napisany po prostu jako:

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

kod w próbce przez DTB to prawie to samo, co kompilator C# automatycznie generuje dla ciebie z tego wyrażenia lambda (skompilowanego jako drzewo wyrażeń, ponieważ typem powrotu jest Expression).

Jeśli znasz typ w czasie wykonywania, możesz użyć rozwiązania przez dtb lub możesz wywołać metodę CreateLambda (powyżej) za pomocą Odbicia, która może być wolniejsza, ale pozwala na wpisanie kodu w lambda naturalna C#:

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

zaletą tego podejścia jest to, że kod w CreateLambda może być o wiele bardziej skomplikowana, co byłoby naprawdę trudne do zrobienia za pomocą wyrażenia drzew wyraźnie.

+0

Cześć Tomas! Muszę poprawić swoje umiejętności komunikacyjne w programowaniu, które znam, znam hahahhę (ale nie martw się, nad tym pracuję:). Zaktualizowałem pytanie, aby przedstawić to, co naprawdę mam na myśli. Ładny refactor! +1 – SDReyes

+0

@SDReyes: "w runtime" był ważnym punktem. Nadal możesz używać ładnej składni C# (bez jawnie konstruowania drzewek wyrażeń). Zobacz moją zaktualizowaną odpowiedź. –

+0

Witaj Tomas !, Zgadzam się z tobą. to podejście pozwala na łatwe implementowanie złożonych lambdów w metodzie CreateLambda (z tylko kompromisem wydajności). Tym razem zastosuję podejście dtb, ponieważ używamy już wielu wyrażeń w komponencie, nad którym pracujemy, i chcę zachować spójność między kodem:). ale z przyjemnością zastosuję twoje w kolejnych scenariuszach! Dobra robota Tomas! pozdrowienia. SD – SDReyes

Powiązane problemy