使用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
中的代码可能要复杂得多,而使用表达式树很难明确地完成。