2010-05-17 17 views
9

Puede usar Lambda Expression Objects para representar una lambda como expresión.Llamar a un método genérico usando expresiones Lambda (y un tipo conocido solo en tiempo de ejecución)

¿Cómo se crea un Lambda Expression Object que representa una llamada a un método genérico, si solo conoce el tipo -que utiliza para la firma del método genérico- en tiempo de ejecución?

Por ejemplo:

Quiero crear una Lambda Expression Objects para llamar: public static TSource Last<TSource>(this IEnumerable<TSource> source)

Pero sólo sé lo que es TSource en tiempo de ejecución.

+0

Esto no está del todo claro. ¿Qué método sobre qué objeto estás tratando de crear? ¿Desea una referencia al último método genérico con una expresión lambda? – casperOne

+0

@CasperOne: Hola Casper! a) Estoy intentando crear una instancia de ** TheObject **, que hace referencia a ** TheMethod **. b) sí, quiero hacer referencia al último método con una expresión lambda (me refiero a objeto de expresión lambda). Gracias:) – SDReyes

Respuesta

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

o

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

No entiendo totalmente la cuestión, pero el código que escribió DTB podría escribirse simplemente como:

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

El código en la muestra por DTB es prácticamente lo mismo que el compilador de C# genera automáticamente para usted a partir de esta expresión lambda (compilada como árbol de expresiones, porque el tipo de devolución es Expression).

Si conoce el tipo en tiempo de ejecución, puede usar la solución por dtb o puede invocar el método CreateLambda (arriba) usando Reflection, que puede ser más lento, pero le permite escribir el código en la lambda en el C natural #:

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

lo bueno de este enfoque es que el código en CreateLambda puede ser mucho más complicado, lo que sería muy difícil de hacer uso de los árboles de expresión explícita.

+0

Hola Tomas! Necesito mejorar mis habilidades de comunicación de programación. Lo sé, lo sé jajaja (pero no te preocupes, estoy trabajando en ello). Actualicé la pregunta para representar lo que realmente quise decir. Buen refactor! +1 – SDReyes

+0

@SDReyes: "en tiempo de ejecución" fue el punto importante. Sin embargo, todavía puedes usar la buena sintaxis de C# para esto (sin construir explícitamente árboles de expresión). Ver mi respuesta actualizada. –

+0

Hola Tomas !, estoy de acuerdo contigo. este enfoque le permite implementar lambdas fácilmente complejos dentro del método CreateLambda (con solo una compensación de rendimiento). Voy a usar el enfoque dtb esta vez, porque ya estamos usando muchas expresiones en el componente en el que estamos trabajando, y quiero mantener la coherencia entre el código:). ¡Pero también me complacerá implementar la suya en los próximos escenarios! Buen trabajo Tomás! Saludos. Dakota del Sur – SDReyes

Cuestiones relacionadas