RuntimeReflectionExtensions.GetRuntimeMethod不能按预期工作 [英] RuntimeReflectionExtensions.GetRuntimeMethod does not work as expected
问题描述
在以下情况下,是否有人知道为什么调用GetRuntimeMethod返回null?
Does anyone have any clue on why calling GetRuntimeMethod is returning null for the following case?
_toListMethod = typeof(Enumerable).GetRuntimeMethod("ToList", new Type[] { typeof(IEnumerable<>) });
它应该像它的工作方式一样
It should work just like it does for:
_castMethod = typeof(Enumerable).GetRuntimeMethod("Cast", new Type[] { typeof(IEnumerable) });
我试图通过运行以下代码来调试它:
I tried to debug this by running the following code:
var bah = typeof (Enumerable).GetRuntimeMethods().Where(m => m.Name.Contains("ToList"));
var derp = bah.First().GetParameters();
令我惊讶的是,第一行返回一个包含我要获取的MethodInfo的集合,第二行确认期望的参数类型为IEnumerable<>.
To my surprise, the first line returns a collection which contains the MethodInfo I am trying to get and the second line confirms that the expected paramter type is IEnumerable<>.
两个方法签名Cast和ToList相似,我看不出任何获取ToList的MethodInfo失败的原因.
The two method signatures, Cast and ToList, are similar and I cannot see any reason why getting the MethodInfo for ToList would fail.
此代码在TargetFrameworkProfile设置为Profile78的可移植类库上运行.
This code is running on a Portable Class Library with TargetFrameworkProfile set to Profile78.
谢谢!
更新:在我找到一个好的解决方案之前,有一个 ugly 变通办法适用于我:
Update: Until I have a good solution, there is one ugly workaround which works for me:
_toListMethod = typeof(Enumerable).GetRuntimeMethods().First(m => m.Name.Contains("ToList"));
推荐答案
我查找了签名,它们看起来像这样:
I looked up the signatures, and they look like this:
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source);
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source);
我认为可能在GetRunTimeMethod
和带有通用参数的扩展方法上有些麻烦,因为这不起作用:
I believe there might be something fishy going on with GetRunTimeMethod
and extension methods with generic parameters since this does not work:
var intToListMethod = typeof(IEnumerable<int>).GetRuntimeMethod("ToList", new Type[] { typeof(IEnumerable<int>) });
我花了一些时间尝试为您的所需行为创建有效的扩展方法,然后我想到了下面的代码段.它对我有用.
I took some time and tried to create a valid extension method for your needed behaviour, and I came up with the code snippet below. It works for me.
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
方法均未产生任何结果.
Below I've attached the IL produced when compiling my third case and your two cases. None of the ToList
methods produce any result.
// 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
这篇关于RuntimeReflectionExtensions.GetRuntimeMethod不能按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!