使用Lambda表达式调用通用方法(以及仅在运行时已知的类型)

您可以使用Lambda表达式对象将lambda表示为表达式。

如果在运行时只知道用于generics方法签名的类型,如何创建表示generics方法调用的Lambda表达式对象 ?

例如:

我想创建一个Lambda表达式对象来调用: public static TSource Last( this IEnumerable source )

但我只知道TSource在运行时是什么。

 static Expression, T>> CreateLambda() { var source = Expression.Parameter( typeof(IEnumerable), "source"); var call = Expression.Call( typeof(Enumerable), "Last", new Type[] { typeof(T) }, source); return Expression.Lambda, 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) } 

我不完全理解这个问题,但是dtb编写的代码可以简单地写成:

 class MyUtils { public static Expression, T>> CreateLambda() { 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在于CreateLambda中的代码可能要复杂得多,而使用表达式树很难明确地完成。