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
的类型是IEnumerable
而typeof(IEnumerable<>)
前者是后者的实例化(它是generics类型定义),具有由ToList
方法定义的generics类型参数。
通常,很难定义一个简单的API来绑定到这样的方法,因为C#没有提供简单的方法(非reflection)来获得表示在方法上定义的generics参数的类型。