Как получить MethodInfo метода интерфейса, внедряя MethodInfo метода класса?
У меня есть MethodInfo
метода интерфейса и Type
класса, который реализует интерфейс.
Я хочу найти MethodInfo
метода класса, который реализует метод интерфейса.
Простой method.GetBaseDefinition()
не работает с методами интерфейса.
Поиск по имени тоже не будет работать, потому что при явном применении метода интерфейса он может иметь любое имя (да, а не на С#).
Итак, каков правильный способ выполнения этого, который охватывает все возможности?
Ответы
Ответ 1
Хорошо, я нашел способ, используя GetInterfaceMap.
var map = targetType.GetInterfaceMap(interfaceMethod.DeclaringType);
var index = Array.IndexOf(map.InterfaceMethods, interfaceMethod);
if (index == -1)
{
//this should literally be impossible
}
return map.TargetMethods[index];
Ответ 2
Хммм - не уверен насчет правильного пути, но вы можете сделать это, просматривая все интерфейсы вашего типа, а затем ища интерфейсы для метода. Не уверен, что вы можете сделать это напрямую без циклического перебора интерфейсов, так как вы застряли без GetBaseDefinition().
Для моего интерфейса с одним методом (MyMethod) и моего типа (MyClass), который реализует этот метод, я могу использовать это:
MethodInfo interfaceMethodInfo = typeof(IMyInterface).GetMethod("MyMethod");
MethodInfo classMethodInfo = null;
Type[] interfaces = typeof(MyClass).GetInterfaces();
foreach (Type iface in interfaces)
{
MethodInfo[] methods = iface.GetMethods();
foreach (MethodInfo method in methods)
{
if (method.Equals(interfaceMethodInfo))
{
classMethodInfo = method;
break;
}
}
}
Вы должны убедиться, что MethodInfo.Equals работает, если два метода имеют разные имена. Я даже не знал, что это возможно, потому что я С# 'er
EDIT
Далее к комментариям от Тома ниже. Он прав - мое решение, приведенное выше, на самом деле не делает то, что просит ОП, оно просто получает тот же интерфейс MethodInfo
по другому маршруту: typeof(MyClass).GetInterfaces()
Чтобы получить MethodInfo
из класса Type, вам нужно сделать что-то вроде этого:
classMethodINfo = typeof(MyClass)
.GetMethods()
.Where(m => m.Name == interfaceMethodInfo.Name)
.Where(m => m.ReturnType == interfaceMethodInfo.ReturnType)
.Where(m => m.GetParameters().Select(p => p.ParameterType).SequenceEqual(interfaceMethodInfo.GetParameters().Select(p => p.ParameterType)))
.FirstOrDefault();
Обратите внимание, что приведенная выше реализация немного наивна, но в большинстве случаев должна работать. В основном я ищу тип MethodInfo, который соответствует имени (не обязательно всегда true и не учитывает регистр в моем примере), типу возврата и тем же параметрам в том же порядке.
НО - это все еще не работает в случае, если имя отличается (как спрашивает ОП). В этом случае я действительно не могу придумать иного пути, кроме как использовать MethodInfo
из интерфейса.
Имейте в виду, что, поскольку у вас есть MethodInfo
из интерфейса, вы все равно можете использовать его для вызова метода в экземпляре самого класса, передав его в MethodInfo.Invoke
.