如何为采用泛型参数的泛型函数调用 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();
我知道我可以使用 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();