RuntimeReflectionExtensions.GetRuntimeMethod无法按预期工作

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

_toListMethod = typeof(Enumerable).GetRuntimeMethod("ToList", new Type[] { typeof(IEnumerable) }); 

它应该像它一样工作:

 _castMethod = typeof(Enumerable).GetRuntimeMethod("Cast", new Type[] { typeof(IEnumerable) }); 

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

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

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

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

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

谢谢!

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

 _toListMethod = typeof(Enumerable).GetRuntimeMethods().First(m => m.Name.Contains("ToList")); 

我抬起签名,他们看起来像这样:

 public static List ToList(this IEnumerable source); public static IEnumerable Cast(this IEnumerable source); 

我相信GetRunTimeMethod 可能会有一些可疑的东西和带有generics参数的扩展方法,因为这不起作用:

 var intToListMethod = typeof(IEnumerable).GetRuntimeMethod("ToList", new Type[] { typeof(IEnumerable) }); 

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

 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(); } } 

这称为:

 var myLookup = typeof(Enumerable).GetRuntimeMethodsExt("ToList", typeof(IEnumerable<>)); 

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

 // ToList IL_0001: ldtoken System.Collections.Generic.IEnumerable 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 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 

你期待这个……

typeof(Enumerable).GetRuntimeMethod(“ToList”,new Type [] {typeof(IEnumerable <>)});

……要归还……

public static List ToList(这个IEnumerable源码);

…因为您假设参数source的类型等于typeof(IEnumerable<>) 。 它不是。 参数source的类型是IEnumerabletypeof(IEnumerable<>)前者是后者的实例化(它是generics类型定义),具有由ToList方法定义的generics类型参数。

通常,很难定义一个简单的API来绑定到这样的方法,因为C#没有提供简单的方法(非reflection)来获得表示在方法上定义的generics参数的类型。