从非泛型静态中的泛型重载方法获取 RuntimeMethodInfo class
Get RuntimeMethodInfo from generic overloaded methods in non-generic static class
我尝试在静态 class 中获取运行时方法信息。我在 class 中有四个静态方法,每个名称都相等,参数名称也相等。唯一的区别是它们的类型。四种方法中的一种具有字符串参数,因此很容易获取方法信息。但是其他人不工作。我找到了一些建议,但都没有用。
所有测试代码都在这里。
class Program {
static void Main(string[] args) {
//ok
var stringMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(string) });
//not working
var dictMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(Dictionary<,>) });
//not working
var genericMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(object) });
//not working
var listMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(List<>) });
//not working
var res = typeof(TestClass)
.GetRuntimeMethods()
.Where(x => x.Name.Equals("TestMethod"))
.Select(m => new { Method = m, Parameters = m.GetParameters() })
.FirstOrDefault(p =>
p.Parameters.Length == 1
&& p.Parameters[0].ParameterType.IsGenericType
&& p.Parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(ICollection<>)
);
}
}
public static class TestClass {
public static bool TestMethod(string item) {
return true;
}
public static bool TestMethod<TKey, TValue>(Dictionary<TKey, TValue> item) {
return true;
}
public static bool TestMethod<T>(T item) {
return true;
}
public static bool TestMethod<T>(List<T> item) {
return true;
}
}
如果您使用的是 .net core 2.1 或更高版本,则可以使用 Type.MakeGenericMethodParameter
来引用方法的通用参数。您可以使用它来创建将与 GetMethod
一起使用的泛型类型参数(不适用于 GetRuntimeMethod
)。
var stringMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(string) });
Type[] dictionaryTypeParameters = { typeof(Dictionary<,>).MakeGenericType(Type.MakeGenericMethodParameter(0), Type.MakeGenericMethodParameter(1)) };
MethodInfo dictMethodInfo = typeof(TestClass).GetMethod("TestMethod", 2, dictionaryTypeParameters);
MethodInfo listMethodInfo = typeof(TestClass).GetMethod("TestMethod", 1, new[] { typeof(List<>).MakeGenericType(Type.MakeGenericMethodParameter(0)) });
MethodInfo genericMethodInfo = typeof(TestClass).GetMethod("TestMethod", 1, new[] { Type.MakeGenericMethodParameter(0) });
关于该主题的一些有趣阅读 here。
假设我们想使用此方法为各种 TestMethod
获取任何 MethodInfo
。请注意,它们都只有一个参数,因此 p.Parameters.Length == 1
没有用:
- 定义为
bool TestMethod(string item)
。我们可以使用
.FirstOrDefault(p => p.Method.IsGenericMethod)
- 定义为
bool TestMethod<TKey, TValue>(Dictionary<TKey, TValue> item)
.FirstOrDefault(p =>
p.Method.IsGenericMethod &&
p.Method.GetGenericArguments().Length == 2)
- 定义为
bool TestMethod<T>(T item)
.FirstOrDefault(p =>
p.Method.IsGenericMethod &&
p.Parameters[0].ParameterType == m.Method.GetGenericArguments()[0]
)
- 定义为
TestMethod<T>(List<T> item)
.FirstOrDefault(p =>
p.Method.IsGenericMethod &&
p.Parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(List<>)
)
如果是 generic
方法,您必须查询 MethodInfo
对象以获取适当的方法。
您可以按照下面的方式进行 -
var dictMethodInfo = typeof(TestClass).GetMethods().Single(m => m.Name == "TestMethod" && m.IsGenericMethod &&
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.IsGenericType &&
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Dictionary<,>));
在您的情况下,为 TestMethod<T>
获取 MethodInfo
有点棘手,但下面应该可行 -
var genericMethodInfo = typeof(TestClass).GetMethods().Single(m => m.Name == "TestMethod" && m.IsGenericMethod &&
!m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.IsGenericType);
最终代码 -
var stringMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(string) });
var dictMethodInfo = typeof(TestClass).GetMethods().Single(m => m.Name == "TestMethod" && m.IsGenericMethod &&
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.IsGenericType &&
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Dictionary<,>));
var genericMethodInfo = typeof(TestClass).GetMethods().Single(m => m.Name == "TestMethod" && m.IsGenericMethod &&
!m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.IsGenericType);
var listMethodInfo = typeof(TestClass).GetMethods().Single(m => m.Name == "TestMethod" && m.IsGenericMethod &&
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.IsGenericType &&
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(List<>));
我尝试在静态 class 中获取运行时方法信息。我在 class 中有四个静态方法,每个名称都相等,参数名称也相等。唯一的区别是它们的类型。四种方法中的一种具有字符串参数,因此很容易获取方法信息。但是其他人不工作。我找到了一些建议,但都没有用。
所有测试代码都在这里。
class Program {
static void Main(string[] args) {
//ok
var stringMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(string) });
//not working
var dictMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(Dictionary<,>) });
//not working
var genericMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(object) });
//not working
var listMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(List<>) });
//not working
var res = typeof(TestClass)
.GetRuntimeMethods()
.Where(x => x.Name.Equals("TestMethod"))
.Select(m => new { Method = m, Parameters = m.GetParameters() })
.FirstOrDefault(p =>
p.Parameters.Length == 1
&& p.Parameters[0].ParameterType.IsGenericType
&& p.Parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(ICollection<>)
);
}
}
public static class TestClass {
public static bool TestMethod(string item) {
return true;
}
public static bool TestMethod<TKey, TValue>(Dictionary<TKey, TValue> item) {
return true;
}
public static bool TestMethod<T>(T item) {
return true;
}
public static bool TestMethod<T>(List<T> item) {
return true;
}
}
如果您使用的是 .net core 2.1 或更高版本,则可以使用 Type.MakeGenericMethodParameter
来引用方法的通用参数。您可以使用它来创建将与 GetMethod
一起使用的泛型类型参数(不适用于 GetRuntimeMethod
)。
var stringMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(string) });
Type[] dictionaryTypeParameters = { typeof(Dictionary<,>).MakeGenericType(Type.MakeGenericMethodParameter(0), Type.MakeGenericMethodParameter(1)) };
MethodInfo dictMethodInfo = typeof(TestClass).GetMethod("TestMethod", 2, dictionaryTypeParameters);
MethodInfo listMethodInfo = typeof(TestClass).GetMethod("TestMethod", 1, new[] { typeof(List<>).MakeGenericType(Type.MakeGenericMethodParameter(0)) });
MethodInfo genericMethodInfo = typeof(TestClass).GetMethod("TestMethod", 1, new[] { Type.MakeGenericMethodParameter(0) });
关于该主题的一些有趣阅读 here。
假设我们想使用此方法为各种 TestMethod
获取任何 MethodInfo
。请注意,它们都只有一个参数,因此 p.Parameters.Length == 1
没有用:
- 定义为
bool TestMethod(string item)
。我们可以使用
.FirstOrDefault(p => p.Method.IsGenericMethod)
- 定义为
bool TestMethod<TKey, TValue>(Dictionary<TKey, TValue> item)
.FirstOrDefault(p =>
p.Method.IsGenericMethod &&
p.Method.GetGenericArguments().Length == 2)
- 定义为
bool TestMethod<T>(T item)
.FirstOrDefault(p =>
p.Method.IsGenericMethod &&
p.Parameters[0].ParameterType == m.Method.GetGenericArguments()[0]
)
- 定义为
TestMethod<T>(List<T> item)
.FirstOrDefault(p =>
p.Method.IsGenericMethod &&
p.Parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(List<>)
)
如果是 generic
方法,您必须查询 MethodInfo
对象以获取适当的方法。
您可以按照下面的方式进行 -
var dictMethodInfo = typeof(TestClass).GetMethods().Single(m => m.Name == "TestMethod" && m.IsGenericMethod &&
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.IsGenericType &&
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Dictionary<,>));
在您的情况下,为 TestMethod<T>
获取 MethodInfo
有点棘手,但下面应该可行 -
var genericMethodInfo = typeof(TestClass).GetMethods().Single(m => m.Name == "TestMethod" && m.IsGenericMethod &&
!m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.IsGenericType);
最终代码 -
var stringMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(string) });
var dictMethodInfo = typeof(TestClass).GetMethods().Single(m => m.Name == "TestMethod" && m.IsGenericMethod &&
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.IsGenericType &&
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Dictionary<,>));
var genericMethodInfo = typeof(TestClass).GetMethods().Single(m => m.Name == "TestMethod" && m.IsGenericMethod &&
!m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.IsGenericType);
var listMethodInfo = typeof(TestClass).GetMethods().Single(m => m.Name == "TestMethod" && m.IsGenericMethod &&
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.IsGenericType &&
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(List<>));