Как в IMetadataImport или MonoCecil узнать, доступен ли метод во внутреннем классе из других сборок? - PullRequest
2 голосов
/ 24 сентября 2011

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

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

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

Ответы [ 2 ]

3 голосов
/ 03 октября 2011

Если я возьму этот пример 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?

1 голос
/ 02 октября 2011

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

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

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

...