为Enumerable.OfType()获取Enumerable.First()vs MethodInfo的MethodInfo?

时间:2016-01-14 14:05:52

标签: c# linq reflection

  • 要获得MethodInfo Enumerable.OfType<T>(),我们可以使用:

    typeof(System.Linq.Enumerable).GetMethod("OfType", new Type[] { typeof(IEnumerable) })
    
  • 对于Enumerable.Sum()MethodInfo,我们可以使用类似的内容:

    typeof(System.Linq.Enumerable).GetMethod("Sum", new Type[] { typeof(IEnumerable<int>) })
    
  • 但是,对于'Enumerable.Reverse()` MethodInfo我们必须要做的事情:

    typeof(Enumerable).GetMember("Reverse").OfType<MethodInfo>().First()
    
  • 当方法重载时,例如使用谓词(例如Enumerable.First()),get MethodInfo调用变得更加kludgy *

    typeof(Enumerable).GetMember("First").OfType<MethodInfo>().Where(m => m.GetParameters().Length == 1).First()
    

所有四种方法都显示在Enumerable中定义的扩展方法,这些方法可以扩展IEnumerableIEnumerable<>IEnumerable<>的特定专精,例如IEnumerable<int>

为什么调用typeof(Enumerable).GetMethod("Reverse", new Type { typeof(IEnumerable<>)})typeof(Enumerable).GetMethod("First", new Type[] { typeof(IEnumerable<>) })会返回null而不是MethodInfo - 对象?前两种扩展方法和后两种扩展方法有什么区别?

*:见Get methodinfo for Enumerable.DefaultIfEmptyhttps://stackoverflow.com/a/6384066/814206以及Select Right Generic Method with Reflection

1 个答案:

答案 0 :(得分:3)

Enumerable.OfType<T>()

签名:

public static IEnumerable<TResult> OfType<TResult>(
    this IEnumerable source
)

Enumerable.Reverse()

签名:

public static IEnumerable<TSource> Reverse<TSource>(
    this IEnumerable<TSource> source
)

OfType<>需要IEnumerableReverse<>需要IEnumerable<>,而不是IEnumerable

Sum期望IEnumerable<int>,可以作为参数类型传入。

获取MethodInfo的另一种类型安全方式是:

public MethodInfo GetMethod(Expression<Action> e)
{
    var methodCall = e.Body as MethodCallExpression;
    if (methodCall.Method.IsGenericMethod)
        return methodCall.Method.GetGenericMethodDefinition();
    return methodCall.Method;
}

var method = GetMethod(() => Enumerable.Empty<int>().First());
var overLoadedMethod = GetMethod(() => Enumerable.Empty<int>().First(a => true));

请注意,我们正在获取泛型方法,即使我们已经要求int模板 - 所以如果您不知道{{1在编译时。

也适用于您没有以下实例的类型:

TSource