В IMetadataImport или MonoCecil как я могу узнать, доступен ли метод во внутреннем классе из других сборок?

Один из случаев, когда открытый метод внутреннего класса может быть доступен извне сборки, - это если метод реализует методы интерфейса или переопределяет виртуальные методы, определенные в общедоступном базовом классе.

Используя IMetadataImport, как узнать, так ли это для определенного mdMethodDef?

Обновление: я также хотел бы знать, как сделать это в Mono.Cecil, поскольку это может помочь мне понять, как это сделать в IMetaDataImport.

2 ответа

Решение

Если я возьму этот пример C#:

public interface ITest
{
    void DoSomething();
}

public class Test : ITest
{
    public void DoSomething()
    {
    }
}

Здесь Test класс успешно реализует ITest интерфейс, как определено в спецификации C# (например, 13.4.2 Отображение интерфейса)

Если вы изучите результат этого кода в скомпилированной сборке (используя такой инструмент, как.NET Reflector или ILDASM), вы увидите следующее:

.method public hidebysig newslot virtual final instance void DoSomething() cil managed
{
    .maxstack 8
    L_0000: nop 
    L_0001: ret 
}

И... да... в метаданных сборки нет ничего, что связывало бы метод DoSomething в Test с методом DoSomething в ITest.

В VB.NET все по-другому, вам нужно добавить Implements ключевое слово, чтобы убедиться, что оно компилируется:

Public Interface ITest

    Sub DoSomething()

End Interface


Public Class Test
    Implements ITest


    Public Sub DoSomething() Implements ITest.DoSomething

    End Sub
End Class

Как вы видите, с VB.NET вам нужно явно связать метод в классе с методом в интерфейсе, и если вы проанализируете, что IL было создано в сборке в случае VB.NET, вы обнаружите это:

.method public newslot virtual final instance void DoSomething() cil managed
{
    .override TestVB.ITest::DoSomething
    .maxstack 8
    L_0000: nop 
    L_0001: nop 
    L_0002: ret 
}

Итак, для сборки, скомпилированной с помощью VB, информация есть, а для сборки на C#- нет. Это зависит от языка. Двигатель CLR на самом деле будет отображаться во время выполнения.

Если вы можете внедрить сборки в ваш процесс, этот код может помочь вам определить отображение интерфейса:

    InterfaceMapping im = typeof(Test).GetInterfaceMap(typeof(ITest));

Но если вам нужно определить это только по метаданным, вам придется написать этот код самостоятельно. Это не так просто, особенно с генериками. Также не забывайте, что в C# публичный метод может неявно реализовывать несколько интерфейсов.

Ссылка, которая может помочь: Mono.Cecil что-то вроде Type.GetInterfaceMap?

Вот небольшая помощь с Сесилом - она ​​не покрывает 100% вашего вопроса, но может помочь вам разобраться достаточно, как есть, или с небольшой дополнительной работой.

Многие из жандармских правил должны проверять видимость методов (или типов, полей), поэтому был создан метод расширения IsVisible для обработки большинства необходимых проверок. И в большинстве случаев я имею в виду, что есть еще одна вещь, которая еще не реализована - это поддержка атрибута [ InternalVisibleTo].

Для методов взгляды в MethodRocks.cs, другие файлы содержат методы расширения IsVisible для TypeDefinition и FieldDefinition и множество других методов расширений, которые вы можете найти полезными при работе с Cecil.

Другие вопросы по тегам