В 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.