如果我在一个封闭的generics类型上有一个MethodInfo,那么有一种简单的方法来切换这些类型吗?

假设我有类似Nullable.HasValue 。 无论如何将其转换为Nullable.HasValue

我知道一个常规的generics方法我可以做methodInfo.GetGenericMethod()但我没有看到一种方法来为该方法的类型做,而不需要做更多的reflection开销。 如果我已经有了这个方法,为什么我要再次反思?

有趣的是,这些方法都具有相同的MetadataToken ,这使得更令人印象深刻的是,不知何故,Module.ResolveMember似乎正在推出正确的方法。

有没有办法用Module.ResolveMethod做到这Module.ResolveMethod ? 本质上,方法和类型都可以具有通用参数,我可能需要切换它们。 由于MethodInfo始终表示其标记相同且标记表示MethodInfo是该方法的最开放版本。 我只需要将它转换为我的类型。

编辑:更多挖掘,看起来像List.AddList.Add元数据令牌,我从中检索实际上生活在我的模块中,而通用定义存在于不同的模块中。

一旦我检索成员,我真的不想做reflection,因为很难解决被调用的完全相同的方法。

好吧也许我只是愚蠢,但为什么这不起作用::

 var methodinfo = typeof(List).GetMethod("Add"); var handle = methodinfo.MetaDataToken; var methodinfo2 = methodinfo.Module.ResolveMethod(handle,new []{typeof(string)},null); 

为什么methodInfo2说它是Add(T)而不是Add(string)

您可以使用MethodBase.GetMethodFromHandle在一行中执行此操作,但是为了使用此方法,您必须传递typeof(List)而不仅仅是typeof(string)

 var methodinfo = typeof(List).GetMethod("Add"); var methodinfo2 = MethodBase.GetMethodFromHandle(methodinfo.MethodHandle, typeof (List).TypeHandle); Console.WriteLine(methodinfo); Console.WriteLine(methodinfo2); 

此链接包括上述示例以及ResolveMethod无法工作的原因。

https://www.re-motion.org/blogs/mix/archive/2009/08/12/trying-to-resolve-a-method-in-a-closed-generic-type.aspx

你可以通过多一点反思轻松完成。 没有反思,你不能神奇地做到这一点。

  static void Main(string[] args) { PropertyInfo intHasValue = typeof (int?).GetProperty("HasValue"); PropertyInfo boolHasValue = ChangeGenericType(intHasValue, typeof (bool)); } public static PropertyInfo ChangeGenericType(PropertyInfo property, Type targetType) { Type constructed = property.DeclaringType; Type generic = constructed.GetGenericTypeDefinition(); Type targetConstructed = generic.MakeGenericType(new[] {targetType}); return targetConstructed.GetProperty(property.Name); } 

当然,这仅适用于具有单个类型参数的generics类型,但如果需要,可以推广到更多。

你必须再次思考,因为方法是不同的。 虽然HasValue的唯一区别是MethodInfo.DeclaringType,但Value属性的差异是MethodInfo.ReturnType。

解决了它。 但最大的问题是这是一种安全的方法吗? 有什么我可能在这里做错了吗?

  public static MethodInfo Convert(this MethodInfo method,params Type[] DeclaringTypeArguments) { var baseType = method.DeclaringType.GetGenericTypeDefinition().MakeGenericType(DeclaringTypeArguments); return MethodInfo.GetMethodFromHandle(method.MethodHandle, baseType.TypeHandle) as MethodInfo; } public static void Main(String[] args) { List list = new List(); Action action = list.Add; Console.WriteLine(action.Method.Convert(typeof(string))); Console.Read(); }