In IMetadataImport or MonoCecil, how can I find out out if a method in an internal class is accessible from other assembiles?
One of the cases where a public method of an internal class might be accessible from outside the assembly is if the method implements interface methods or overrides virtual methods that are defined in 开发者_运维技巧a public base class.
Using IMetadataImport, how can find out if this is the case for a specific mdMethodDef?
Update: I'd also like to know how to do this in Mono.Cecil, as that might help me figure out how to do it in IMetaDataImport.
If I take this C# sample:
public interface ITest
{
void DoSomething();
}
public class Test : ITest
{
public void DoSomething()
{
}
}
Here, the Test
class successfully implements the ITest
interface, as defined in C# specification (for example 13.4.2 Interface mapping)
If you examine the result of this code in the compiled assembly (using a tool such as .NET Reflector or ILDASM), you will see this:
.method public hidebysig newslot virtual final instance void DoSomething() cil managed
{
.maxstack 8
L_0000: nop
L_0001: ret
}
And... yes...there is nothing here in the assembly metadata that will relate the DoSomething method in Test to the DoSomething method in ITest.
In VB.NET, it's different, you will need to add an Implements
keyword to make sure it compiles:
Public Interface ITest
Sub DoSomething()
End Interface
Public Class Test
Implements ITest
Public Sub DoSomething() Implements ITest.DoSomething
End Sub
End Class
As you see, with VB.NET, you need to explicitely relate the method in the class with the method in the interface, and if you analyse what IL has been created in the assembly in the VB.NET case, you'll find this:
.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
}
So, with a VB-compiled assembly, the information is there, with a C#-compile assembly, it's not. It depends on the language. The CLR engine will in fact to the mapping at runtime.
If you can inject the assemblies in your process, this code can help you determine interface mapping:
InterfaceMapping im = typeof(Test).GetInterfaceMap(typeof(ITest));
But if you need to determine this only looking at metadata, you'll have to write that code yourself. It's not that easy, especially with generics. Also don't forget in C#, a public method can implicitely implement multiple interfaces.
A link that can help: Mono.Cecil something like Type.GetInterfaceMap?
Here's a bit of help wrt Cecil - it does not cover 100% of your question but it may get you close enough as-is or with a bit of additional work.
Many of Gendarme rules have to check methods (or types, fields) visibility so an extension method, IsVisible, was created to deal with most of required checks. And by most I mean there's one thing that is not (yet) implemented is support for the [InternalVisibleTo] attribute.
For methods looks in MethodRocks.cs, other files contains IsVisible extension methods for TypeDefinition and FieldDefinition and a lot of other extensions method you can find useful when working with Cecil.
精彩评论