如何使用reflection来获取generics类型的扩展方法

从各种来源的teh interwebs我收集了以下function:

public static Nullable TryParseNullable(this Nullable t, string input) where T : struct { if (string.IsNullOrEmpty(input)) return default(T); Nullable result = new Nullable(); try { IConvertible convertibleString = (IConvertible)input; result = new Nullable((T)convertibleString.ToType(typeof(T), CultureInfo.CurrentCulture)); } catch (InvalidCastException) { } catch (FormatException) { } return result; } 

我把它变成了一个扩展方法,如果我直接调用它就可以正常工作:

 int? input = new int?().TryParseNullable("12345"); 

当我尝试使用另一个generics函数的上下文中的reflection来调用它时,我的问题就出现了。 SO充满了描述如何获得generics方法和静态方法的MethodInfo的答案,但我似乎无法以正确的方式将它们组合在一起。
我已经正确地确定传递的generics类型本身是generics类型( Nullable ),现在我想使用reflection来调用Nullable上的TryParseNullable扩展方法:

 public static T GetValue(string name, T defaultValue) { string result = getSomeStringValue(name); if (string.IsNullOrEmpty(result)) return defaultValue; try { if (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Nullable)) { MethodInfo methodInfo; //using the TryParse() of the underlying type works but isn't exactly the way i want to do it //------------------------------------------------------------------------------------------- NullableConverter nc = new NullableConverter(typeof(T)); Type t = nc.UnderlyingType; methodInfo = t.GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, new[] { typeof(string), t.MakeByRefType() }, null); if (methodInfo != null) { var inputParameters = new object[] { result, null }; methodInfo.Invoke(null, inputParameters); return (T) inputParameters[1]; } //start of the problem area //------------------------- Type ttype = typeof(T); //this works but is undesirable (due to reference to class containing the static method): methodInfo = typeof(ParentExtensionsClass).GetMethod("TryParseNullable", BindingFlags.Public | BindingFlags.Static); if (methodInfo != null) Console.WriteLine(methodInfo); //standard way of getting static method, doesn't work (GetMethod() returns null): methodInfo = ttype.GetMethod("TryParseNullable", BindingFlags.Public | BindingFlags.Static); if (methodInfo != null) Console.WriteLine(methodInfo); //Jon Skeet's advised method, doesn't work in this case (again GetMethod() returns null): //(see footnote for link to this answer) methodInfo = ttype.GetMethod("TryParseNullable"); methodInfo = methodInfo.MakeGenericMethod(ttype); if (methodInfo != null) Console.WriteLine(methodInfo); //another random attempt (also doesn't work): methodInfo = ttype.GetMethod("TryParseNullable", BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, new[] { typeof(string) }, null); if (methodInfo != null) Console.WriteLine(methodInfo); } // if we get this far, then we are not handling the type yet throw new ArgumentException("The type " + defaultValue.GetType() + " is not yet supported by GetValue.", "T"); } catch (Exception e) { [snip] } } 

有人能让我摆脱苦难吗?
typeof(T)返回正确的类型信息,我想可能我在GetMethod()调用时使用它有点不正确,或者我没有通过调用GetMethod()指定正确的参数。

1. 链接到引用的Jon Skeet答案

问题是扩展方法不会修改它们“扩展”的类型。 幕后实际发生的是编译器透明地将所有对相关对象进行的调用转换为对静态方法的调用。

即。

 int? input = new int?().TryParseNullable("12345"); // becomes... int? input = YourClass.TryParseNullable(new int?(), "12345"); 

从那里可以明显看出为什么它没有通过reflection出现。 这也解释了为什么必须为命名空间设置using指令,其中定义了YourClass ,以使扩展方法对编译器可见。 至于如何实际获取该信息,我不确定是否有办法,缺少运行所有声明的类型(如果你在编译时知道那些信息,可能是一个有趣的类的过滤列表)对于在它们上定义了ExtensionMethodAttribute[ExtensionMethod] )的静态方法,然后尝试解析参数列表的MethodInfo以便在它们处理Nullable<>