6

System.Reflection does not (AFAIK) support reflecting on global methods in an assembly. At the assembly level, I must start with the root types.

My compiler can produce assemblies with global methods, and my standard bootstrap lib is a dll that includes some global methods. My compiler uses System.Reflection to import assembly metadata at compile time. It seems if I depend on System.Reflection, global methods are not a possibility. The cleanest solution is to convert all of my standard methods to class static methods, but the point is, my language allows global methods, and the CLR supports it, but System.Reflection leaves a gap.

ildasm shows the global methods just fine, but I assume it does not use System.Reflection itself and goes right to the metadata and bytecode.

Besides System.Reflection, is anyone aware of any other 3rd party reflection or disassembly libs that I could make use of (assuming I will eventually release my compiler as free, BSD licensed open source).

SOLVED: There is no gap, except in my knowledge. Thanks for pointing out GetModules, guys!

Abyx
  • 12,345
  • 5
  • 44
  • 76
codenheim
  • 20,467
  • 1
  • 59
  • 80

3 Answers3

10

Have you looked at Module.GetMethods?

Returns the global methods defined on the module

You can get all the modules of your assembly using Assembly.GetModules().

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Beat me to it, but I have to admit that I haven't actually tried it. Good question and good answer. – Brian Rasmussen Apr 22 '10 at 21:41
  • you probably have some high level power that will let you know if the documentation is accurate or not just by looking at it :) – Brian Rasmussen Apr 22 '10 at 21:46
  • 1
    I have MSDN + a desk full of compiler and .NET reference books, including "Expert .NET 2.0 IL Assembler" and I still miss things like this, embarassing. :| – codenheim Apr 22 '10 at 22:02
4

You keep beating on a gap between the CLR and System.Reflection, but actually, there's no such thing as a global method or a global field.

They are just traditional static methods and static fields that are defined in particular type, named <Module>, which has to be present in every valid assembly.

As Jon said, you can use Module.GetMethod and Module.GetField to operator on the members of the type.

If you want more control, you can just use Mono.Cecil.

Jb Evain
  • 17,319
  • 2
  • 67
  • 67
  • 1
    I'm not "beating on anything" except my keyboard. I just missed this info, which is why I asked on SO. I learn more everyday. Thanks for the answer. :) – codenheim Apr 22 '10 at 21:59
  • @Jb: Regarding Mono.Cecil, and I am aware of it and surely interested in it. The only reason I passed over it was the license. When I release my code, it will be BSD license. I will support building against Mono, but I cannot include a dependency on any tools that aren't common to the official CLR and Mono. Of course, thats all speculative right now, anyway. – codenheim Apr 22 '10 at 22:29
  • @mrjoltcola: Mono.Cecil is licensed under the MIT/X11 license (similar to the BSD), so it shouldn't be an issue. – Jb Evain Apr 23 '10 at 06:21
  • There _is_ such a thing as a global method, you just cannot access it with C# / VB. You can create one by hand using [`ModuleBuilder.DefineGlobalMethod`](http://msdn.microsoft.com/en-us/library/67s2c85d.aspx). They are not stored in ``, that's just a way Reflector makes them visible. Also see http://stackoverflow.com/questions/3796688/whats-a-global-method – Abel Mar 19 '12 at 11:07
  • @Abel, you're wrong. Reflector here shows you how they're stored in the assembly, that is, in the `` type. – Jb Evain Mar 19 '12 at 12:58
  • Try ILDASM on your class. You won't find the type ``. It's there implicitly and denotes global methods. The cctor of the `` is loaded when the module (i.e., the assembly) is loaded (it's the module constructor). Any method in this section can be called without specifying the class. You refer to Reflector, and I use that too, but it shows it the way it does as a convenience. It's a representation, not the actual source (try to roundtrip compile System.Data, you won't succeed). See also Jon's answer: why do you think MS calls them "global methods"? – Abel Mar 19 '12 at 13:46
  • Dear @Abel, as the author a library to read and write .net assemblies (Mono.Cecil) outside of Reflection , I think I have a clue about how types and methods are serialized in the metadata. Global methods and fields are just a convention for methods and fields attached to the type (the first and mandatory hidden type of assemblies). Please read the ECMA-335, and open an assembly in ildasm showing the metadata tables and rows to actually understand what's underneath the convention ildasm uses. Thanks. – Jb Evain Mar 19 '12 at 14:18
  • 1
    Thanks for taking the time to explain it to me further. I'm aware of the standard. I assume you mean section 10.8, which talks about _Global fields and methods_ stored in an invisible abstract public class. I was wrong in saying that the type `` is not there, I see it in the binary as well (thought it was _implicitly_ there, my bad). But still, this is a notion of global members, where the name of the member must be unique between loaded modules or an error occurs. How can that not be "global"? – Abel Mar 19 '12 at 16:15
2

Note, that Module.GetMethod() without parameters won't return all module's methods.
Use GetMethods(BindingFlags) instead.

C++/CLI example:

#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)));
}
Abyx
  • 12,345
  • 5
  • 44
  • 76