Selim Balci
Selim Balci

Reputation: 910

Get .NET Class Hierarchy

I am trying to get all the objects in .NET Framework with their hierarchy order with their namespaces and put them into a tree structure or some sort for academic purposes in C#. I am trying to do this for a specific .NET framework platform. Is there a way to do such thing?

Request: List everything (classes, enums, structures etc.) under System.Threading namespace

Result:

Constructors:

Structures:

Delegates:

Enumerations:

Pretty much what I want is something like this. - MSDN

Many thanks.


Edit: I am not asking for a code sample or someone to write the code for me - I just can't figure out where to start so I am looking for tips.

Upvotes: 1

Views: 1097

Answers (3)

xanatos
xanatos

Reputation: 111890

Someone (Groo) has alread given the "theoretical" reply about how you should do it, but note that there are at least two strong caveats:

  • any Microsoft assembly could contain a System.Threading class (and technically any assembly could contain it, even yours, but it is bad etiquette to do it)
  • if you want to explore a "base" assembly (mscorlib, System, ...) from a different version of .NET than the one you are running from then you'll need Mono.Cecil or similar library, because with Reflection you can't load a different version of a base assembly than the one you are running)

And now some very simple code:

var assemblyNames = new[]
{
    "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
    "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
    "System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
};

var nss = new[]
{
    "System.Threading"
};


// Begin real code

var assemblies = Array.ConvertAll(assemblyNames, Assembly.Load);
var nss2 = Array.ConvertAll(nss, x => x + ".");

var types = assemblies.SelectMany(x => x.ExportedTypes).Where(x => nss2.Any(y => x.FullName.StartsWith(y))).ToArray();

// The Delegate check is taken from http://mikehadlow.blogspot.it/2010/03/how-to-tell-if-type-is-delegate.html
var classes = types.Where(x => x.IsClass && !typeof(Delegate).IsAssignableFrom(x)).ToArray();
var structs = types.Where(x => x.IsValueType && !x.IsEnum).ToArray();
var enums = types.Where(x => x.IsEnum).ToArray();
var delegates = types.Where(x => x.IsClass && typeof(Delegate).IsAssignableFrom(x)).ToArray();

// There is a DeclaringType property to see what Type is declaring them
var constructors = types.SelectMany(x => x.GetConstructors(BindingFlags.Public | BindingFlags.Instance)).ToArray();

Upvotes: 2

Matthew Strawbridge
Matthew Strawbridge

Reputation: 20630

If you can get hold of the corresponding XML file for the framework you're interested in, you might find it easier to transform that than to extract this information directly from the code.

Upvotes: 1

vgru
vgru

Reputation: 51264

Here are some guidelines on how to get started:

  1. You will need to use Reflection, i.e. the classes from the System.Reflection namespaces (Assembly, ConstructorInfo, PropertyInfo, and similar). As stated on MSDN:

    The classes in the System.Reflection namespace, together with System.Type, enable you to obtain information about loaded assemblies and the types defined within them, such as classes, interfaces, and value types. You can also use reflection to create type instances at run time, and to invoke and access them.

  2. Start by getting an instance of the Assembly class. You can either pass a type from the assembly you want to access (any type, like System.Threading.Barrier for example) and use Assembly.GetAssembly:

    var assembly = Assembly.GetAssembly(typeof(System.Threading.Barrier));
    

    Or, if you're going to iterate through a folder of .dll files, you can use use Assembly.LoadFrom:

    var assembly = Assembly.LoadFrom("path-to-System.Threading.dll");
    
  3. Once you have the assembly instance, you will want to iterate through the types and do further reflection upon them:

    foreach (var type in assembly.GetTypes())
    {
        var constructors = type.GetConstructors();
        var fields = type.GetFields();
        var properties = type.GetProperties();
        ...
    }
    
  4. The Type class, apart from these methods, also contains various properties which allow you to see if the specified type is a class or a struct (Type.IsValueType, Type.IsInterface, Type.IsAbstract, etc.), see if one type inherits or implement a different one (Type.IsAssignableFrom(otherType), Type.GetInterfaces), and similar things.

Upvotes: 4

Related Questions