我有IQueryable
所以,我需要在IQueryable中声明的计数方法的方法信息。
这是来自MSDN的签名(IQueryable<>):
public static int Count<TSource>(
this IQueryable<TSource> source
)
这就是我走多远:
Expression expr; //this is expression which holds my IQueryable<T>
MethodInfo mi = expr.Type.GetMethod("Count", BindingFlags.Static | BindingFlags.Public, null, new[] { expr.Type }, null);
但我的 mi 总是为空;
我也试过:
mi = typeof(IQueryable<>).GetMethod("Count", BindingFlags.Static | BindingFlags.Public, null, new[] { expr.Type }, null);
但又是空的。
我的最终目标是:
Expression.Call(mi, expr);
更新:这就是我获得总和扩展方法的方式:
MethodInfo sum = typeof(Queryable).GetMethod("Sum", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(IQueryable<decimal>) }, null);
这有效,但这个 Sum 方法不是通用的。虽然它是静态的。
你需要破解IQueryable<T>
类型的泛型参数并使用它; 拥有该方法的类型也不是IQueryable<T>
,它是Queryable
- 如果你考虑一下 - 接口不能有静态方法(好吧,正如评论者指出的那样,在 C# 中):)。
此外,因为它是一个泛型方法,所以你不能以你尝试过的方式匹配参数:因为你需要传递泛型类型定义IQuerable<TSource>
- 而不是泛型类型IQueryable<int>
或任何实际表达式。
相反,您可以在Queryable
类型上查找名为"Count"的静态方法的单参数版本:
Type genericArgument = expr.GetGenericArguments()[0];
MethodInfo countMethod = typeof(Queryable)
.GetMethods(BindingFlags.Static | BindingFlags.Public)
//narrow the search before doing 'Single()'
.Single(mi => mi.Name == "Count"
// this check technically not required, but more future proof
&& mi.IsGenericMethodDefinition
&& mi.GetParameters().Length == 1)
.MakeGenericMethod(genericArgument);
//now you can bind to 'countMethod'
2017年3月7日更新 - 显然,框架中的某些更改阻止了代码示例的原始版本 - 这是一个应该可以工作的更新版本
再深入一点 - 该方法的签名是:
public static int Count<TSource>(
this IQueryable<TSource> source
)
因此,虽然参数类型是IQueryable<TSource>
但它是通用的,而不是TSource
类型——因此你需要钓到你的IQueryable<TSource>
表达式并获取它的泛型参数的原因。 您还应该能够在这里看到我对参数的含义。
让编译器为你获取方法。
Type genericArgument = expr.GetGenericArguments()[0];
var fakeExp = (Expression<Func<IQueryable<int>, int>>)(q => q.Count());
var mi = ((MethodCallExpression)fakeExp.Body).Method.GetGenericMethodDefinition().MakeGenericMethod(genericArgument);