#729 – Dumping Out All Types in .NET Framework, part II
December 5, 2012 Leave a comment
Here’s an updated copy of the code that iterates through all .NET assemblies, dumping out type information. This code iterates through all .NET assemblies and dumps out a master list of all types, organized by namespace. Information about the type members is dumped out for each type and everything is written to a file. The code has also been updated to descend into all sub-directories of the .NET runtime directory.
When I run this against .NET 4.0.30319, I get a total of 50,380 types, in 872 namespaces.
class Program { static void Main() { int totalNamespaces = 0; int totalTypes = 0; AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += CurrentDomain_ReflectionOnlyAssemblyResolve; SortedList<string, SortedList<string, Type>> fullList = new SortedList<string, SortedList<string, Type>>(); DirectoryInfo di = new DirectoryInfo(RuntimeEnvironment.GetRuntimeDirectory()); foreach (FileInfo fi in di.GetFiles("*",SearchOption.AllDirectories)) { Trace.WriteLine("File: {0}", fi.FullName); try { Assembly assem = Assembly.LoadFrom(fi.FullName); if (assem != null) { ExtractListOfTypes(assem, ref fullList, ref totalNamespaces, ref totalTypes); } } catch (Exception xx) { Trace.WriteLine(string.Format("EXCEPTION on {0}: {1}", fi.FullName, xx.ToString())); } } DumpTypeList(fullList, totalNamespaces, totalTypes); } static Assembly CurrentDomain_ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args) { return Assembly.ReflectionOnlyLoad(args.Name); } private static void ExtractListOfTypes(Assembly assem, ref SortedList<string, SortedList<string, Type>> theList, ref int totalNamespaces, ref int totalTypes) { if (theList == null) throw new Exception("Uninitialized list"); foreach (Type t in assem.GetTypes()) { string theNamespace = t.Namespace != null ? t.Namespace : "(global)"; // Add namespace if it's not already in list if (!theList.ContainsKey(theNamespace)) { theList.Add(theNamespace, new SortedList<string, Type>()); totalNamespaces++; } // And add type under appropriate namespace if (!theList[theNamespace].ContainsKey(t.FullName)) { theList[theNamespace].Add(t.FullName, t); totalTypes++; } } return; } private static void DumpTypeList(SortedList<string, SortedList<string, Type>> theList, int totalNamespaces, int totalTypes) { using (StreamWriter writer = new StreamWriter(@"C:\Test\AllTypes.txt")) { writer.WriteLine(string.Format("Total Namespaces: {0}", totalNamespaces)); writer.WriteLine(string.Format("Total Types: {0}", totalTypes)); foreach (KeyValuePair<string, SortedList<string, Type>> kvp in theList) { writer.WriteLine(string.Format("Namespace: [{0}]", kvp.Key)); foreach (KeyValuePair<string, Type> kvpInner in kvp.Value) { Type t = (Type)kvpInner.Value; writer.WriteLine(string.Format(" Type: [{0}] ({1})", t.FullName, TypeIndicator(t))); DumpTypeInfo(t, writer); } writer.WriteLine(); } } } private static void DumpTypeInfo(Type t, StreamWriter writer) { writer.WriteLine(string.Format(" Assembly: {0}", t.Assembly.FullName)); if (t.BaseType != null) writer.WriteLine(string.Format(" Base Type: {0}", t.BaseType.FullName)); MemberInfo[] members = t.GetMembers(); if (members.Length > 0) { writer.WriteLine(" Members:"); foreach (MemberInfo mi in members) { writer.WriteLine(string.Format(" {0} ({1})", mi.ToString(), mi.MemberType)); } } } private static string TypeIndicator(Type t) { string typeIndicator = "?"; if ((t.BaseType != null) && (t.BaseType.FullName == "System.MulticastDelegate")) typeIndicator = "delegate"; else if (t.IsClass) { if (t.IsNested) typeIndicator = "Nested class"; else typeIndicator = "class"; } else if (t.IsInterface) typeIndicator = "interface"; else if (t.IsValueType) typeIndicator = "struct"; else if (t.IsEnum) typeIndicator = "enum"; return typeIndicator; } }