使用反射选择正确的通用方法 [英] Select Right Generic Method with Reflection
问题描述
我想通过反射选择正确的泛型方法然后调用它.
I want to select the right generic method via reflection and then call it.
通常这很容易.例如
var method = typeof(MyType).GetMethod("TheMethod");
var typedMethod = method.MakeGenericMethod(theTypeToInstantiate);
然而,当方法有不同的通用重载时,问题就开始了.例如 System.Linq.Queryable-class 中的静态方法.Where"方法有两种定义
However the issue start when there are different generic overloads of the method. For example the static-methods in the System.Linq.Queryable-class. There are two definitions of the 'Where'-method
static IQueryable<T> Where(this IQueryable<T> source, Expression<Func<T,bool>> predicate)
static IQueryable<T> Where(this IQueryable<T> source, Expression<Func<T,int,bool>> predicate)
这意味着 GetMethod 不起作用,因为它无法消除两者.因此我想选择正确的.
This meand that GetMethod doesn't work, because it cannot destiguish the two. Therefore I want to select the right one.
到目前为止,我经常只采用第一种或第二种方法,这取决于我的需要.像这样:
So far I often just took the first or second method, depending on my need. Like this:
var method = typeof (Queryable).GetMethods().First(m => m.Name == "Where");
var typedMethod = method.MakeGenericMethod(theTypeToInstantiate);
但是我对此并不满意,因为我假设第一种方法是正确的.我宁愿通过参数类型找到正确的方法.但我不知道怎么做.
However I'm not happy with this, because I make a huge assumption that the first method is the right one. I rather want to find the right method by the argument type. But I couldn't figure out how.
我通过传递类型"进行了尝试,但没有奏效.
I tried it with passing the 'types', but it didn't work.
var method = typeof (Queryable).GetMethod(
"Where", BindingFlags.Static,
null,
new Type[] {typeof (IQueryable<T>), typeof (Expression<Func<T, bool>>)},
null);
有谁知道我如何通过反射找到正确"的通用方法.例如,Queryable 类中Where"方法的正确版本?
So has anyone an idea how I can find the 'right' generic method via reflection. For example the right version of the 'Where'-method on the Queryable-class?
推荐答案
可以做到,但不漂亮!
例如,要获得问题中提到的 Where
的第一个重载,您可以这样做:
For example, to get the first overload of Where
mentioned in your question you could do this:
var where1 = typeof(Queryable).GetMethods()
.Where(x => x.Name == "Where")
.Select(x => new { M = x, P = x.GetParameters() })
.Where(x => x.P.Length == 2
&& x.P[0].ParameterType.IsGenericType
&& x.P[0].ParameterType.GetGenericTypeDefinition() == typeof(IQueryable<>)
&& x.P[1].ParameterType.IsGenericType
&& x.P[1].ParameterType.GetGenericTypeDefinition() == typeof(Expression<>))
.Select(x => new { x.M, A = x.P[1].ParameterType.GetGenericArguments() })
.Where(x => x.A[0].IsGenericType
&& x.A[0].GetGenericTypeDefinition() == typeof(Func<,>))
.Select(x => new { x.M, A = x.A[0].GetGenericArguments() })
.Where(x => x.A[0].IsGenericParameter
&& x.A[1] == typeof(bool))
.Select(x => x.M)
.SingleOrDefault();
或者如果你想要第二个重载:
Or if you wanted the second overload:
var where2 = typeof(Queryable).GetMethods()
.Where(x => x.Name == "Where")
.Select(x => new { M = x, P = x.GetParameters() })
.Where(x => x.P.Length == 2
&& x.P[0].ParameterType.IsGenericType
&& x.P[0].ParameterType.GetGenericTypeDefinition() == typeof(IQueryable<>)
&& x.P[1].ParameterType.IsGenericType
&& x.P[1].ParameterType.GetGenericTypeDefinition() == typeof(Expression<>))
.Select(x => new { x.M, A = x.P[1].ParameterType.GetGenericArguments() })
.Where(x => x.A[0].IsGenericType
&& x.A[0].GetGenericTypeDefinition() == typeof(Func<,,>))
.Select(x => new { x.M, A = x.A[0].GetGenericArguments() })
.Where(x => x.A[0].IsGenericParameter
&& x.A[1] == typeof(int)
&& x.A[2] == typeof(bool))
.Select(x => x.M)
.SingleOrDefault();
这篇关于使用反射选择正确的通用方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!