System.Reflection - 全局方法不适用于反射。

6
System.Reflection(据我所知)不支持反射程序集中的全局方法。在程序集级别上,必须从根类型开始。我的编译器可以生成带有全局方法的程序集,我的标准引导库是包含一些全局方法的dll。我的编译器使用System.Reflection在编译时导入程序集元数据。如果我依赖于System.Reflection,则似乎不可能使用全局方法。最清洁的解决方案是将所有标准方法转换为类静态方法,但问题是,我的语言允许全局方法,而CLR也支持它,但System.Reflection存在缺陷。
ildasm可以很好地显示全局方法,但我认为它不使用System.Reflection本身,而是直接访问元数据和字节码。
除了System.Reflection之外,还有谁知道任何其他第三方反射或反汇编库可以使用(假设我最终将发布我的编译器作为自由的、BSD许可的开源软件)。
已解决:除了我自己的知识之外,没有任何缺口。感谢指出GetModules,伙计们!
3个回答

10

抢我说的话了,但我必须承认我实际上还没有尝试过。好问题和好答案。 - Brian Rasmussen
您可能拥有某些高级技能,可以通过查看文档来判断其准确性 :) - Brian Rasmussen
1
我有MSDN和一桌子编译器和.NET参考书籍,包括《Expert .NET 2.0 IL Assembler》,但我仍然会错过像这样的东西,很尴尬。 :| - codenheim

4
你一直在强调CLR和System.Reflection之间的差距,但实际上,并不存在全局方法或全局字段。
它们只是传统的静态方法和静态字段,定义在特定类型中,命名为,必须存在于每个有效的程序集中。
正如Jon所说,你可以使用Module.GetMethod和Module.GetField来操作该类型的成员。
如果你需要更多的控制,可以使用Mono.Cecil

1
我并没有“打击”任何东西,只是在敲键盘而已。我只是错过了这个信息,所以在SO上问了一下。我每天都在学习新知识。感谢你的回答。 :) - codenheim
有全局方法这样的东西,只是你不能使用C# / VB访问它。您可以使用ModuleBuilder.DefineGlobalMethod手动创建一个。它们不存储在<Module>中,那只是Reflector使它们可见的一种方式。另请参阅https://dev59.com/WFDTa4cB1Zd3GeqPLroK。 - Abel
@Abel,你错了。反射器在这里展示了它们在程序集中的存储方式,也就是在“<Module>”类型中。 - Jb Evain
尝试在您的类上使用ILDASM。您不会找到类型<Module>。它是隐式存在的,表示全局方法。<Module>的cctor在加载模块(即程序集)时加载(它是模块构造函数)。此部分中的任何方法都可以在不指定类的情况下调用。您提到了Reflector,我也使用它,但它以一种方便的方式显示它。这是一种表示,而不是实际的源代码(尝试往返编译System.Data,您将无法成功)。另请参阅Jon的答案:为什么您认为MS称它们为“全局方法”? - Abel
1
感谢您花时间进一步向我解释。我知道这个标准。我想您是指第10.8节,它讨论了存储在一个不可见的抽象公共类中的全局字段和方法。我之前说类型<Module>不存在是错误的,我在二进制文件中也看到了它(我以为它是_隐含_存在的,我的错)。但仍然存在全局成员的概念,其中成员的名称必须在加载的模块之间唯一,否则会出现错误。这怎么可能不是“全局”的呢? - Abel
显示剩余3条评论

2
请注意,不带参数的Module.GetMethod()将不返回模块的所有方法。
请改用GetMethods(BindingFlags)
C++/CLI示例:
#using <System.dll>
using namespace System;
using namespace System::Reflection;
using namespace System::Diagnostics;

bool has_main(array<MethodInfo^>^ methods)
{
    for each(auto m in methods)
        if(m->Name == "main")
            return true;
    return false;
}

int main()
{
    auto module = Assembly::GetExecutingAssembly()->GetModules(false)[0];
    Debug::Assert(has_main(module->GetMethods()) == false);
    Debug::Assert(has_main(module->GetMethods(BindingFlags::Static | BindingFlags::NonPublic)));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接