Как получить 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.