在 IMetadataImport 或 MonoCecil 中,如何确定内部类中的方法是否可以从其他程序集访问?

发布于 2024-12-06 04:50:46 字数 208 浏览 4 评论 0原文

可以从程序集外部访问内部类的公共方法的情况之一是该方法实现接口方法或重写公共基类中定义的虚拟方法。

使用 IMetadataImport,如何查明特定 mdMethodDef 是否属于这种情况?

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

酷到爆炸 2024-12-13 04:50:46

如果我采用此 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?

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?

你在我安 2024-12-13 04:50:46

这里有一些关于 Cecil 的帮助 - 它并没有 100% 涵盖你的问题,但它可能会让你足够接近原样或者需要一些额外的工作。

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

对于方法,请查找 MethodRocks.cs ,其他文件包含 TypeDefinition 和 FieldDefinition 的 IsVisible 扩展方法,以及许多其他扩展方法,您在使用 Cecil 时会发现有用。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文