Mono.Cecil что-то вроде Type.GetInterfaceMap? - PullRequest
6 голосов
/ 07 февраля 2011

System.Reflection.Type содержит GetInterfaceMap , которые помогают определить, какой метод реализует некоторый метод из интерфейса.

Содержит ли Mono.Cecil что-то подобное? Или как реализовать такое поведение?

1 Ответ

7 голосов
/ 27 апреля 2011

Нет, Сесил не предоставляет такой метод, потому что Сесил дает нам только метаданные CIL, как они есть.(Существует проект Cecil.Rocks, который содержит некоторые полезные методы расширения, но не этот)

В методах MSIL есть атрибут 'overrides', который содержит ссылки на методы, которые переопределяет этот метод (в Cecil естьдействительно свойство переопределяет в классе MethodDefinition).Однако этот атрибут используется только в некоторых особых случаях, таких как явная реализация интерфейса.Обычно этот атрибут остается пустым, и методы, которые переопределяются данным методом, основаны на соглашениях.Эти соглашения описаны в стандарте ECMA CIL.Короче говоря, метод переопределяет методы, которые имеют одинаковое имя и одинаковую подпись.

Следующие фрагменты кода могут помочь вам, а также это обсуждение: http://groups.google.com/group/mono-cecil/browse_thread/thread/b3c04f25c2b5bb4f/c9577543ae8bc40a

    public static bool Overrides(this MethodDefinition method, MethodReference overridden)
    {
        Contract.Requires(method != null);
        Contract.Requires(overridden != null);

        bool explicitIfaceImplementation = method.Overrides.Any(overrides => overrides.IsEqual(overridden));
        if (explicitIfaceImplementation)
        {
            return true;
        }

        if (IsImplicitInterfaceImplementation(method, overridden))
        {
            return true;
        }

        // new slot method cannot override any base classes' method by convention:
        if (method.IsNewSlot)
        {
            return false;
        }

        // check base-type overrides using Cecil's helper method GetOriginalBaseMethod()
        return method.GetOriginalBaseMethod().IsEqual(overridden);
    }

    /// <summary>
    /// Implicit interface implementations are based only on method's name and signature equivalence.
    /// </summary>
    private static bool IsImplicitInterfaceImplementation(MethodDefinition method, MethodReference overridden)
    {
        // check that the 'overridden' method is iface method and the iface is implemented by method.DeclaringType
        if (overridden.DeclaringType.SafeResolve().IsInterface == false ||
            method.DeclaringType.Interfaces.None(i => i.IsEqual(overridden.DeclaringType)))
        {
            return false;
        }

        // check whether the type contains some other explicit implementation of the method
        if (method.DeclaringType.Methods.SelectMany(m => m.Overrides).Any(m => m.IsEqual(overridden)))
        {
            // explicit implementation -> no implicit implementation possible
            return false;
        }

        // now it is enough to just match the signatures and names:
        return method.Name == overridden.Name && method.SignatureMatches(overridden);
    }

    static bool IsEqual(this MethodReference method1, MethodReference method2)
    {
        return method1.Name == method2.Name &&  method1.DeclaringType.IsEqual(method2.DeclaringType);
    }
    // IsEqual for TypeReference is similar...
...