【问题标题】:System.Reflection - Global methods aren't available for reflectionSystem.Reflection - 全局方法不可用于反射
【发布时间】:2010-04-22 21:36:27
【问题描述】:

System.Reflection 不 (AFAIK) 支持在程序集中反映全局方法。在汇编级别,我必须从根类型开始。

我的编译器可以生成带有全局方法的程序集,而我的标准引导库是一个包含一些全局方法的 dll。我的编译器使用 System.Reflection 在编译时导入程序集元数据。看来如果我依赖 System.Reflection,全局方法是不可能的。最干净的解决方案是将我所有的标准方法转换为类静态方法,但重点是,我的语言允许全局方法,并且 CLR 支持它,但 System.Reflection 留下了一个空白。

ildasm 很好地显示了全局方法,但我认为它不使用 System.Reflection 本身并直接访问元数据和字节码。

除了 System.Reflection,是否有人知道我可以使用的任何其他 3rd 方反射或反汇编库(假设我最终将我的编译器作为免费的、BSD 许可的开源版本发布)。

已解决:没有差距,除了我的知识。感谢您指出 GetModules,伙计们!

【问题讨论】:

    标签: .net reflection clr ildasm


    【解决方案1】:

    你看过Module.GetMethods吗?

    返回模块上定义的全局方法

    您可以使用Assembly.GetModules() 获取程序集的所有模块。

    【讨论】:

    • 击败我,但我不得不承认我还没有真正尝试过。好问题和好答案。
    • 您可能拥有一些高级别的权力,可以通过查看文档来让您知道文档是否准确:)
    • 我有 MSDN + 桌子上堆满了编译器和 .NET 参考书,包括“Expert .NET 2.0 IL Assembler”,但我仍然怀念这样的东西,很尴尬。 :|
    【解决方案2】:

    您一直在 CLR 和 System.Reflection 之间寻找差距,但实际上,没有全局方法或全局字段之类的东西。

    它们只是以特定类型定义的传统静态方法和静态字段,名为<Module>,必须存在于每个有效程序集中。

    正如 Jon 所说,您可以使用 Module.GetMethodModule.GetField 对类型的成员进行操作。

    如果你想要更多的控制,你可以使用Mono.Cecil

    【讨论】:

    • 除了我的键盘之外,我没有“在任何东西上敲打”。我只是错过了这个信息,这就是我问的原因。我每天都学到更多。感谢您的回答。 :)
    • @Jb:关于 Mono.Cecil,我知道并且肯定对它感兴趣。我通过它的唯一原因是许可证。当我发布我的代码时,它将是 BSD 许可证。我将支持针对 Mono 进行构建,但我不能包含对官方 CLR 和 Mono 不常见的任何工具的依赖。当然,无论如何,这都是推测。
    • @mrjoltcola:Mono.Cecil 是在 MIT/X11 许可(类似于 BSD)下获得许可的,所以这应该不是问题。
    • 这样一个全局方法,你只是不能用C#/VB访问它。您可以使用ModuleBuilder.DefineGlobalMethod 手动创建一个。它们不存储在<Module> 中,这只是Reflector 使它们可见的一种方式。另见stackoverflow.com/questions/3796688/whats-a-global-method
    • 感谢您花时间向我进一步解释。我知道标准。我假设您的意思是第 10.8 节,其中讨论了存储在不可见的抽象公共类中的 全局字段和方法。我说<Module> 类型不存在是错误的,我也在二进制文件中看到它(我认为它是隐式,我的错)。但是,这仍然是全局成员的概念,其中成员的名称在加载的模块之间必须是唯一的,否则会发生错误。这怎么可能不是“全球性的”?
    【解决方案3】:

    请注意,不带参数的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)));
    }
    

    【讨论】:

      猜你喜欢
      • 2011-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-14
      相关资源
      最近更新 更多