【问题标题】:Get MethodInfo for LINQ's Any() method?获取 LINQ 的 Any() 方法的 MethodInfo?
【发布时间】:2014-09-28 14:41:26
【问题描述】:

我正在尝试构建一个调用 LINQ 的 Any() 方法的表达式,但我似乎找不到传递给 Type.GetMethod() 的正确参数。

从文档看来,Any() 是作为 Enumerable 类的成员实现的,这似乎可行,因为这显示给名为“Any”的方法:

var enumerableType = typeof (Enumerable);
var foo = enumerableType.GetMethods().Where(m => m.Name == "Any").ToList();

当我使用名为“Any”的方法时,我得到了一个 AmbiguousMatchException。

有两种 Any() 方法,在 Enumerable 中,一个接受一个参数 IEnumerable,另一个接受一个 IEnumerable 和一个 Func。我想要第二个,理论上,我需要做的就是传递一个包含两种类型的数组:

var bar = enumerableType.GetMethod("Any", new[] { typeof(IEnumerable<>), typeof(Func<,>) });

但这总是返回 null。

我做错了什么?

【问题讨论】:

标签: c# linq reflection


【解决方案1】:
var foo = enumerableType.GetMethods(BindingFlags.Static | BindingFlags.Public)
            .First(m => m.Name == "Any" && m.GetParameters().Count() == 2);

【讨论】:

  • m.GetParameters().Count() == 2 对于可移植性可能不是很安全(例如,迁移到更高版本的框架)。您可能想检查该方法的实际参数是什么。
  • 我不知道为什么我没有想到这一点。我在示例中使用 LINQ 来过滤掉“任何”方法。我只是坚持以某种方式将正确的参数传递给 GetMethod()。
【解决方案2】:

如果您想特别确保匹配采用 IEnumerable&lt;&gt;Func&lt;,&gt; 参数的重载,可以使用以下内容(改编自 this answer):

var enumerableType = typeof(Enumerable);
var bar =
(
    from m in enumerableType.GetMethods(BindingFlags.Static | BindingFlags.Public)
    where m.Name == "Any"
    let p = m.GetParameters()
    where p.Length == 2
        && p[0].ParameterType.IsGenericType
        && p[0].ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
        && p[1].ParameterType.IsGenericType
        && p[1].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>)
    select m
).SingleOrDefault();

【讨论】:

    【解决方案3】:

    感谢@JonSkeet 在right direction 中给我指点,这里有几条线:

    var any = typeof(Enumerable).GetMethods().FirstOrDefault(m => m.Name == "Any" && m.IsGenericMethodDefinition && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(IEnumerable<>).MakeGenericType(m.GetGenericArguments()[0]));
    
    var anyWhere = typeof(Enumerable).GetMethods().FirstOrDefault(m => m.Name == "Any" && m.IsGenericMethodDefinition && m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType == typeof(IEnumerable<>).MakeGenericType(m.GetGenericArguments()[0]) && m.GetParameters()[1].ParameterType == typeof(Func<,>).MakeGenericType(m.GetGenericArguments()[0], typeof(bool)));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多