获取 .NET Class 层次结构

Get .NET Class Hierarchy

我正在尝试获取 .NET Framework 中的所有对象及其层次结构顺序及其命名空间,并将它们放入树结构或某种 C# 学术用途中。我正在尝试针对特定的 .NET 框架平台执行此操作。有没有办法做这样的事情?

请求:列出 System.Threading 命名空间

下的所有内容(类、枚举、结构等)

结果:

构造函数:

结构:

代表:

枚举:

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

非常感谢。


编辑:我不是要代码示例或有人为我编写代码 - 我只是不知道从哪里开始,所以我正在寻找提示。

以下是一些入门指南:

  1. 您将需要使用 Reflection,即来自 System.Reflection 命名空间的 classes(AssemblyConstructorInfoPropertyInfo,以及类似的)。如 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. 首先获取 Assembly class 的实例。您可以从要访问的程序集中传递一个类型(任何类型,例如 System.Threading.Barrier)并使用 Assembly.GetAssembly:

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

    或者,如果您要遍历 .dll 文件的文件夹,您可以使用 Assembly.LoadFrom:

    var assembly = Assembly.LoadFrom("path-to-System.Threading.dll");
    
  3. 获得程序集实例后,您将需要遍历类型并对它们进行进一步思考:

    foreach (var type in assembly.GetTypes())
    {
        var constructors = type.GetConstructors();
        var fields = type.GetFields();
        var properties = type.GetProperties();
        ...
    }
    
  4. Type class 除了这些方法外,还包含各种属性,可让您查看指定类型是 class 还是 struct (Type.IsValueType, Type.IsInterface, Type.IsAbstract, etc.), 看看一种类型是否继承或实现了不同的类型 (Type.IsAssignableFrom(otherType), Type.GetInterfaces) , 和类似的东西。

如果您可以 get hold of the corresponding XML file 您感兴趣的框架,您可能会发现转换它比直接从代码中提取此信息更容易。

有人 (Groo) 已经给出了 "theoretical" 回复,说明您应该如何做,但请注意至少有两个强烈的警告:

  • 任何 Microsoft 程序集都可以包含 System.Threading class(从技术上讲 任何 程序集都可以包含它,即使是您的程序集,但这样做是不礼貌的它)
  • 如果您想探索来自不同版本的 "base" 程序集(mscorlibSystem、...) .NET 比你现在 运行 从那时起你将需要 Mono.Cecil 或类似的库,因为使用反射你不能加载与你现在不同版本的基础程序集 运行)

现在是一些非常简单的代码:

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();