可以从程序集外部访问内部类的公共方法的一种情况是,该方法实现了接口方法或覆盖了在公共基类中定义的虚拟方法。
使用 IMetadataImport,如何确定特定 mdMethodDef 是否属于这种情况?
更新:我也想知道如何在 Mono.Cecil 中执行此操作,因为这可能会帮助我弄清楚如何在 IMetaDataImport 中执行此操作。
可以从程序集外部访问内部类的公共方法的一种情况是,该方法实现了接口方法或覆盖了在公共基类中定义的虚拟方法。
使用 IMetadataImport,如何确定特定 mdMethodDef 是否属于这种情况?
更新:我也想知道如何在 Mono.Cecil 中执行此操作,因为这可能会帮助我弄清楚如何在 IMetaDataImport 中执行此操作。
如果我采用这个 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
}
而且...是的...在程序集元数据中没有任何内容可以将 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 之类的 Type.GetInterfaceMap?
这是 Cecil 的一些帮助 - 它不能 100% 涵盖您的问题,但它可能会让您按原样或做一些额外的工作。
许多宪兵规则必须检查方法(或类型、字段)的可见性,因此创建了一个扩展方法IsVisible来处理大多数必需的检查。大多数情况下,我的意思是(尚未)实现的一件事是对 [ InternalVisibleTo ] 属性的支持。
对于MethodRocks.cs中的方法,其他文件包含TypeDefinition 和 FieldDefinition 的IsVisible扩展方法,以及在使用 Cecil 时可以发现的许多其他扩展方法。