Puoi usare gli oggetti espressione lambda per rappresentare una lambda come espressione.
Come si crea un oggetto espressione lambda che rappresenta una chiamata al metodo generico, se si conosce solo il tipo - che si utilizza per la firma del metodo generico - in fase di esecuzione?
Per esempio:
Voglio creare un oggetto espressione lambda per chiamare: public static TSource Last<TSource>( this IEnumerable<TSource> source )
Ma so solo cosa TSource
è in fase di runtime.
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)
}
Non capisco completamente la domanda, ma il codice che dtb ha scritto potrebbe essere scritto semplicemente come:
class MyUtils {
public static Expression<Func<IEnumerable<T>, T>> CreateLambda<T>() {
return source => source.Last();
}
}
Il codice nell'esempio di dtb è praticamente la stessa cosa che il compilatore C # genera automaticamente per te da questa espressione lambda (compilata come albero delle espressioni, perché il tipo restituito è Expression
).
Se conosci il tipo in fase di esecuzione, puoi utilizzare la soluzione con dtb oppure puoi richiamare il metodo CreateLambda
(sopra) utilizzando Reflection, che potrebbe essere più lento, ma ti consente di scrivere il codice nel lambda nel C # naturale:
var createMeth = typeof(MyUtils).GetMethod("CreateLambda");
LambdaExpression l = createMeth.MakeGenericMethod(yourType).Invoke();
La cosa bella di questo approccio è che il codice in CreateLambda
può essere molto più complicato, il che sarebbe davvero difficile da fare usando gli alberi di espressione in modo esplicito.