如何为采用泛型参数的泛型函数调用 GetMethod(不使用 GetMethods)?

How do you call GetMethod for a generic function that takes a generic parameter (without using GetMethods)?

我知道我可以使用 GetMethods 获取方法信息,但我想知道如何在没有 GetMethods 的情况下正确执行此操作。我已经阅读了其他 SO 问题和答案,这些问题和答案表明这是不可能的,或者建议只使用 LINQ,但这并不是问题的真正答案。

从最基本的层面考虑,采用单个泛型参数的静态泛型函数。

private static void Test<T>(T val)
{
}

要获取此方法信息,我们只需调用 Type.GetMethod("Test", BindingFlags.Static | BindingFlags.NonPublic)。但是,如果出于某种原因我们无法使用这个简单的 GetMethod 签名(可能是由于多重重载),那么我们需要提供参数类型。问题是我无法创建与 T val 参数准确匹配的参数类型。有趣的是,我可以从方法信息中获取参数(使用 GetMethods 获取)并将其传递给 GetMethod 以获得所需的结果。这意味着如果只能创建适当的泛型类型(将 IsGenericParameter 设置为 true),那么我觉得这将是完全可能的。

所以这意味着这在 .NET 中是完全可能的,并且只需要创建适当的类型实例。如何创建这些类型实例?如果无法创建它们,为什么不呢?

我创建了 a simple fiddle 来展示这个问题。

它不容易获得,因为您需要的类型实际上是泛型类型参数,只存在于方法/参数定义中。例如,在你的 Test<T>(T val) 中,参数类型是“由 Test<T> 定义的 T”。你不能 construct that,因为它 不是由 组成的。获得 T 的唯一方法是通过 GetParameters().

基本上,剩下的就是:困难的方法 - 即手动。例如:

var method1 = typeof(Program).GetMethods(flags).Single(x => x.Name == "Test"
     && x.IsGenericMethodDefinition && x.GetParameters().Length == 1
      && x.GetParameters()[0].ParameterType == x.GetGenericArguments()[0])
    .MakeGenericMethod(paramTypes1);

显然,如果您知道只有一种 Test(...) 方法,那就更简单了:

var method = typeof(Program).GetMethod("Test", flags)
    .MakeGenericMethod(paramTypes1);

嗯,我不认为这是可能的。 但其他方法(仍然很难,我相信 GetMethods 会更好):

var method1 =
    typeof (Program).GetMember("Test*",
                               BindingFlags.InvokeMethod |
                               BindingFlags.NonPublic | 
                               BindingFlags.Static)
                    .Cast<MethodInfo>()
                    .Single(
                            m =>
                            m.GetGenericArguments().Length == 1 &&
                            m.GetGenericArguments()[0].IsGenericParameter)
                    .MakeGenericMethod(paramTypes1);

当然,您可以省略 MakeGenericMethod 以获得与 method2 完全相同的结果。

这不是调用 GetMethod,而是 "other" 获取泛型方法定义的方法是 "cast" 一个方法组到特定类型,然后对其调用 .Method.GetGenericDefinition()

在您的示例中,您需要的方法签名是 Action<object>,其中 object 只是一个占位符,可以是与通用方法的约束相匹配的任何类型。

var genericMethodDefinition =
    ((Action<object>)Test<object>).Method.GetGenericMethodDefinition();

您可以 select "Test" 的不同重载,使用以下定义为 private static T Test<T>(T val, int counter)

var genericMethodDefinition2 =
    ((Func<object, int, object>)Test<object>).Method.GetGenericMethodDefinition();