#c# #system.reflection #methodinfo
#c# #system.reflection #methodinfo
Вопрос:
Я пытаюсь получить информацию о методе времени выполнения в статическом классе. У меня есть четыре статических метода внутри класса, и каждое имя равно, также имя параметра равно. Единственное различие заключается в их типах. Один из четырех методов имеет строковый параметр, поэтому легко получить информацию о методе. Однако другие не работают. Я нахожу несколько советов, но они не работают.
Весь тестовый код здесь.
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
amp;amp; p.Parameters[0].ParameterType.IsGenericType
amp;amp; 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;
}
}
Комментарии:
1. «не работает» означает, что именно?
2. Возвращает значение null. Они работают, когда только один общий с тем же именем или другим количеством параметров и т. Д. В моем сценарии я всегда получаю null. В коде строка res является примером из stackoverflow. Также он возвращает значение null
3. Извините, что вы ожидаете, что он вернет? Он вернет первый
TestMethod
, для которого существует именно общий параметр on, который имеет общее определениеICollection<>
. У вас нет такого метода.4. ОК. Что такое Dictionary<,>? Как я получаю информацию о каждом методе? Очевидно, что я не могу получить информацию о методе, кроме как с помощью строкового параметра. Итак, я пытаюсь понять, почему? И каково решение?
Ответ №1:
Если вы используете .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) });
Здесь есть интересное чтение по этой теме.
Комментарии:
1. Примечание: я использую .NET 5, и метод GetRuntimeMethod работает и находит ожидаемые методы.
Ответ №2:
Допустим, мы хотели бы использовать этот метод для получения any MethodInfo
для различных TestMethod
. Обратите внимание, что все они имеют ровно один параметр, поэтому 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 amp;amp;
p.Method.GetGenericArguments().Length == 2)
- Определяется как
bool TestMethod<T>(T item)
.FirstOrDefault(p =>
p.Method.IsGenericMethod amp;amp;
p.Parameters[0].ParameterType == m.Method.GetGenericArguments()[0]
)
- Определяется как
TestMethod<T>(List<T> item)
.FirstOrDefault(p =>
p.Method.IsGenericMethod amp;amp;
p.Parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(List<>)
)
Ответ №3:
В случае generic
методов вам необходимо запросить MethodInfo
объект, чтобы получить соответствующий метод.
Вы можете сделать это, как показано ниже —
var dictMethodInfo = typeof(TestClass).GetMethods().Single(m => m.Name == "TestMethod" amp;amp; m.IsGenericMethod amp;amp;
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.IsGenericType amp;amp;
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Dictionary<,>));
В вашем случае получение MethodInfo
for TestMethod<T>
немного сложно, но ниже должно работать —
var genericMethodInfo = typeof(TestClass).GetMethods().Single(m => m.Name == "TestMethod" amp;amp; m.IsGenericMethod amp;amp;
!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" amp;amp; m.IsGenericMethod amp;amp;
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.IsGenericType amp;amp;
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Dictionary<,>));
var genericMethodInfo = typeof(TestClass).GetMethods().Single(m => m.Name == "TestMethod" amp;amp; m.IsGenericMethod amp;amp;
!m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.IsGenericType);
var listMethodInfo = typeof(TestClass).GetMethods().Single(m => m.Name == "TestMethod" amp;amp; m.IsGenericMethod amp;amp;
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.IsGenericType amp;amp;
m.GetGenericMethodDefinition().GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(List<>));