这可能听起来很愚蠢,但我无法获得Queryable.Join(...)
的MethodInfo
。我想得到它,因为如何在泛型方法调用中使用类型变量(c#)
它有2个可用的方法签名,我想获得没有IEqualityComparer的方法签名,所以我需要在GetMethod
中指定Type[]
。
我写了一些像
MethodInfo joinMethod = typeof( Queryable ).GetMethod( "Join", new Type[] { typeof(IEnumerable<>), typeof(Expression<Func<>>), typeof(Expression<Func<>>), typeof(Expression<Func<>>)});
但它不起作用。我不能在上面的泛型中指定类型,因为它们是从外部作为Type
传递的(这就是为什么我需要这个反射)。
谁能告诉我怎么做?谢谢!
使用泛型和反射可能有点乏味。您最好的选择(为了保持简单)是使用GetMethods
并根据您正在寻找的内容进行过滤。
//Overly simplified
MethodInfo joinMethod = typeof(Queryable)
.GetMethods(BindingFlags.Static | BindingFlags.Public)
.Where(m => m.Name == "Join" && m.GetParameters().Length == 5)
.First();
考虑到这一点,此时MethodInfo
是不可调用的。您需要使用joinMethod.MakeGenericMethod(/*type array*/)
创建它的通用版本。在您的例子中,您需要使用4种类型:TOuter, TInner, TKey, result。
var genericJoinMethod = joinMethod.MakeGenericMethod(new Type[]{your types here});
现在您可以使用genericJoinMethod
作为您的期望。
据我所知,这是在编译时不知道类型的唯一方法。
编辑:
考虑到你的评论,我认为它应该是这样的:
MethodInfo joinMethod = typeof(Queryable)
.GetMethods(BindingFlags.Static | BindingFlags.Public)
.Where(m => m.Name == "Join" && m.GetParameters().Length == 5)
.First();
var genericJoinMethod = joinMethod.MakeGenericMethod(typeof(TType), typeof(TType), JoinKeyType, typeof(TType));
result = genericJoinMethod.Invoke( result, new object[] { result, items, OuterKeySelector, InnerKeySelector, ResultSelector } );
在开始实现涉及字符串和参数计数的复杂反射搜索之前,为什么不退一步,让编译器做他更擅长的事情呢?
var fakeExp = (Expression<Func<IQueryable<int>>>)(() => new int[0].AsQueryable().Join(new int[0], x => x, x => x, (x, y) => x));
return ((MethodCallExpression)fakeExp.Body).Method.GetGenericMethodDefinition();
显然,你可以在表达式中放入任何你想要的东西,只要顶层的东西是你的Join方法调用。类型也不重要