有没有人知道为什么在下列情况下调用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&lt;&gt;。
两个方法签名Cast和ToList是相似的,我看不出为什么获取ToList的MethodInfo会失败的原因。
此代码在可移植类库上运行,TargetFrameworkProfile设置为Profile78。
谢谢!
更新:在我有一个好的解决方案之前,有一个丑陋的解决方法对我有用:
_toListMethod = typeof(Enumerable).GetRuntimeMethods().First(m => m.Name.Contains("ToList"));
答案 0 :(得分:4)
我查了签名,他们看起来像这样:
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source);
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source);
我相信可能可能是GetRunTimeMethod
和使用泛型参数的扩展方法,因为这不起作用
var intToListMethod = typeof(IEnumerable<int>).GetRuntimeMethod("ToList", new Type[] { typeof(IEnumerable<int>) });
我花了一些时间并尝试为您所需的行为创建有效的扩展方法,我想出了下面的代码段。它对我有用。
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<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
答案 1 :(得分:1)
你期待这个......
typeof(Enumerable).GetRuntimeMethod(“ToList”,new Type [] {typeof(IEnumerable&lt;&gt;)});
...要归还......
public static List ToList(此IEnumerable源代码);
...因为您假设参数JNICALL
的类型等于source
。它不是。参数typeof(IEnumerable<>)
的类型是source
而IEnumerable<TSource>
前者是后者的实例化(它是泛型类型定义),其中{{1}定义了泛型类型参数方法。
通常,很难定义一个简单的API来绑定到这样的方法,因为C#没有提供简单的方法(非反射)来获得表示在方法上定义的泛型参数的类型。