在IMetadataImport或MonoCecil中,如何查明内部类中的方法是否可以从其他组件中访问?

时间:2011-09-24 11:23:50

标签: .net reflection clr mono.cecil imetadataimport

如果方法实现接口方法或覆盖在公共基类中定义的虚方法,则可以从程序集外部访问内部类的公共方法的一种情况。

使用IMetadataImport,如何找出特定mdMethodDef的情况?

更新:我也想知道如何在Mono.Cecil中执行此操作,因为这可能有助于我弄清楚如何在IMetaDataImport中执行此操作。

2 个答案:

答案 0 :(得分:3)

如果我拿这个C#样本:

public interface ITest
{
    void DoSomething();
}

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

这里,Test类成功实现了ITest接口,如C#规范中定义的那样(例如13.4.2 Interface mapping

如果在已编译的程序集中检查此代码的结果(使用.NET Reflector或ILDASM等工具),您将看到:

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

并且......是的...程序集元数据中没有任何内容可以将Test中的DoSomething方法与ITest中的DoSomething方法相关联。

在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,您需要明确地将类中的方法与接口中的方法相关联,如果您分析在VB.NET案例中的程序集中创建了IL,那么'我会找到这个:

.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 something like Type.GetInterfaceMap?

答案 1 :(得分:1)

这是Cecil的一些帮助 - 它不会覆盖你问题的100%,但它可能会让你足够接近 as-is 或者有一些额外的工作。

许多Gendarme规则必须检查方法(或类型,字段)的可见性,因此创建扩展方法 IsVisible 来处理大多数所需的支票。而大多数我的意思是,有一件事(尚未)实现的是对[InternalVisibleTo]属性的支持。

对于MethodRocks.cs中的方法,其他文件包含TypeDefinition和FieldDefinition的 IsVisible 扩展方法,以及在使用Cecil时可以找到的许多其他扩展方法。