RuntimeReflectionExtensions.GetRuntimeMethod无法按预期工作

Tia*_*ago 8 c# reflection portable-class-library

有没有人知道为什么在下列情况下调用GetRuntimeMethod返回null?

_toListMethod = typeof(Enumerable).GetRuntimeMethod("ToList",  new Type[] { typeof(IEnumerable<>) });
Run Code Online (Sandbox Code Playgroud)

它应该像它一样工作:

_castMethod = typeof(Enumerable).GetRuntimeMethod("Cast", new Type[] { typeof(IEnumerable) });
Run Code Online (Sandbox Code Playgroud)

我尝试通过运行以下代码来调试它:

var bah = typeof (Enumerable).GetRuntimeMethods().Where(m => m.Name.Contains("ToList"));
var derp = bah.First().GetParameters();
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,第一行返回一个集合,其中包含我想要获取的MethodInfo,第二行确认预期的参数类型是IEnumerable <>.

两个方法签名,Cast和ToList是相似的,我看不出为什么为ToList获取MethodInfo会失败的任何原因.

此代码在可移植类库上运行,TargetFrameworkProfile设置为Profile78.

谢谢!

更新:在我有一个很好的解决方案之前,有一个丑陋的解决方法对我有用:

_toListMethod = typeof(Enumerable).GetRuntimeMethods().First(m => m.Name.Contains("ToList"));
Run Code Online (Sandbox Code Playgroud)

fli*_*erg 5

我查了一下签名,它们看起来像这样:

public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source);
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source);
Run Code Online (Sandbox Code Playgroud)

我相信使用泛型参数和扩展方法可能会发生一些可疑的事情,GetRunTimeMethod因为这不起作用:

var intToListMethod = typeof(IEnumerable<int>).GetRuntimeMethod("ToList", new Type[] { typeof(IEnumerable<int>) });
Run Code Online (Sandbox Code Playgroud)

我花了一些时间并尝试为您所需的行为创建一个有效的扩展方法,然后我想出了下面的代码片段。这个对我有用。

public static class RuntimeMethodExtensions
{
 public static MethodInfo GetRuntimeMethodsExt(this Type type, string name, params Type[] types)
 {
  // Find potential methods with the correct name and the right number of parameters
  // and parameter names
  var potentials = (from ele in type.GetMethods()
                    where ele.Name.Equals(name)
                    let param = ele.GetParameters()
                    where param.Length == types.Length
                    && param.Select(p => p.ParameterType.Name).SequenceEqual(types.Select(t => t.Name))
                    select ele);

  // Maybe check if we have more than 1? Or not?
  return potentials.FirstOrDefault();
 }
}
Run Code Online (Sandbox Code Playgroud)

调用如下:

var myLookup = typeof(Enumerable).GetRuntimeMethodsExt("ToList", typeof(IEnumerable<>));
Run Code Online (Sandbox Code Playgroud)

下面我附上了编译我的第三个案例和你的两个案例时产生的 IL。这些ToList方法都不会产生任何结果。

// ToList<int>
IL_0001:  ldtoken     System.Collections.Generic.IEnumerable<System.Int32>
IL_0006:  call        System.Type.GetTypeFromHandle
IL_000B:  ldstr       "ToList"
IL_0010:  ldc.i4.1    
IL_0011:  newarr      System.Type
IL_0016:  stloc.3     // CS$0$0000
IL_0017:  ldloc.3     // CS$0$0000
IL_0018:  ldc.i4.0    
IL_0019:  ldtoken     System.Collections.Generic.IEnumerable<System.Int32>
IL_001E:  call        System.Type.GetTypeFromHandle
IL_0023:  stelem.ref  
IL_0024:  ldloc.3     // CS$0$0000
IL_0025:  call        System.Reflection.RuntimeReflectionExtensions.GetRuntimeMethod
IL_002A:  stloc.0     // _intToListMethod
// ToList<>
IL_002B:  ldtoken     System.Linq.Enumerable
IL_0030:  call        System.Type.GetTypeFromHandle
IL_0035:  ldstr       "ToList"
IL_003A:  ldc.i4.1    
IL_003B:  newarr      System.Type
IL_0040:  stloc.3     // CS$0$0000
IL_0041:  ldloc.3     // CS$0$0000
IL_0042:  ldc.i4.0    
IL_0043:  ldtoken     System.Collections.Generic.IEnumerable<>
IL_0048:  call        System.Type.GetTypeFromHandle
IL_004D:  stelem.ref  
IL_004E:  ldloc.3     // CS$0$0000
IL_004F:  call        System.Reflection.RuntimeReflectionExtensions.GetRuntimeMethod
IL_0054:  stloc.1     // _toListMethod
// Cast<>
IL_0055:  ldtoken     System.Linq.Enumerable
IL_005A:  call        System.Type.GetTypeFromHandle
IL_005F:  ldstr       "Cast"
IL_0064:  ldc.i4.1    
IL_0065:  newarr      System.Type
IL_006A:  stloc.3     // CS$0$0000
IL_006B:  ldloc.3     // CS$0$0000
IL_006C:  ldc.i4.0    
IL_006D:  ldtoken     System.Collections.Generic.IEnumerable<>
IL_0072:  call        System.Type.GetTypeFromHandle
IL_0077:  stelem.ref  
IL_0078:  ldloc.3     // CS$0$0000
IL_0079:  call        System.Reflection.RuntimeReflectionExtensions.GetRuntimeMethod
IL_007E:  stloc.2     // _castMethod
Run Code Online (Sandbox Code Playgroud)