您可以使用Lambda Expression Objects将lambda表示为表达式。
如果在运行时只知道用于泛型方法签名的类型,如何创建表示泛型方法调用的Lambda Expression Object?
例如:
我想创建一个Lambda Expression Objects来调用:
public static TSource Last<TSource>( this IEnumerable<TSource> source )
但我只知道TSource
在运行时是什么。
答案 0 :(得分:26)
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)
}
或
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)
}
答案 1 :(得分:2)
我不完全理解这个问题,但是dtb编写的代码可以简单地写成:
class MyUtils {
public static Expression<Func<IEnumerable<T>, T>> CreateLambda<T>() {
return source => source.Last();
}
}
dtb中的示例中的代码与C#编译器从此lambda表达式自动生成的内容(编译为表达式树,因为返回类型为Expression
)几乎相同。
如果您在运行时知道类型,那么您可以使用dtb的解决方案,也可以使用Reflection调用CreateLambda
方法(上面),这可能比较慢,但允许您编写代码自然C#中的lambda:
var createMeth = typeof(MyUtils).GetMethod("CreateLambda");
LambdaExpression l = createMeth.MakeGenericMethod(yourType).Invoke();
这种方法的好处是CreateLambda
中的代码可能要复杂得多,而使用表达式树很难明确。