RuntimeReflectionExtensions.GetRuntimeMethod不能按预期工作 [英] RuntimeReflectionExtensions.GetRuntimeMethod does not work as expected

查看:72
本文介绍了RuntimeReflectionExtensions.GetRuntimeMethod不能按预期工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下情况下,是否有人知道为什么调用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆