关于c#:通过反射获取命名空间中的所有类型

Getting all types in a namespace via reflection

如何通过C中的反射获得名称空间中的所有类?


下面的代码打印当前程序集中定义的指定namespace中类的名称。正如其他人指出的,名称空间可以分散在不同的模块之间,因此您需要首先获得程序集列表。

1
2
3
4
5
6
string nspace ="...";

var q = from t in Assembly.GetExecutingAssembly().GetTypes()
        where t.IsClass && t.Namespace == nspace
        select t;
q.ToList().ForEach(t => Console.WriteLine(t.Name));

正如flyswat所说,您可以在多个程序集中拥有相同的名称空间(例如System.Collections.Generic)。如果尚未加载所有这些程序集,则必须加载它们。因此,对于完整的答案:

1
2
3
AppDomain.CurrentDomain.GetAssemblies()
                       .SelectMany(t => t.GetTypes())
                       .Where(t => t.IsClass && t.Namespace == @namespace)

除非您想要其他域的类,否则这应该可以工作。要获取所有域的列表,请使用此链接。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System.Reflection;
using System.Collections.Generic;
//...

static List<string> GetClasses(string nameSpace)
{
    Assembly asm = Assembly.GetExecutingAssembly();

    List<string> namespacelist = new List<string>();
    List<string> classlist = new List<string>();

    foreach (Type type in asm.GetTypes())
    {
        if (type.Namespace == nameSpace)
            namespacelist.Add(type.Name);
    }

    foreach (string classname in namespacelist)
        classlist.Add(classname);

    return classlist;
}

注意:上面的代码说明了正在发生的事情。如果要实现它,可以使用简化版本:

1
2
3
4
5
6
7
8
9
10
11
12
using System.Linq;
using System.Reflection;
using System.Collections.Generic;
//...

static IEnumerable<string> GetClasses(string nameSpace)
{
    Assembly asm = Assembly.GetExecutingAssembly();
    return asm.GetTypes()
        .Where(type => type.Namespace == nameSpace)
        .Select(type => type.Name);
}


对于特定程序集、命名空间和类名:

1
2
3
4
5
6
7
8
9
var assemblyName ="Some.Assembly.Name"
var nameSpace ="Some.Namespace.Name";
var className ="ClassNameFilter";

var asm = Assembly.Load(assemblyName);
var classes = asm.GetTypes().Where(p =>
     p.Namespace == nameSpace &&
     p.Name.Contains(className)
).ToList();

注意:项目必须引用程序集


下面是对loaderException错误的修复,您可能会发现,如果其中一个类型子类在另一个程序集中对某个类型进行了赋值,则会出现以下错误:

1
2
3
4
5
6
7
8
9
10
11
12
// Setup event handler to resolve assemblies
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(CurrentDomain_ReflectionOnlyAssemblyResolve);

Assembly a = System.Reflection.Assembly.ReflectionOnlyLoadFrom(filename);
a.GetTypes();
// process types here

// method later in the class:
static Assembly CurrentDomain_ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args)
{
    return System.Reflection.Assembly.ReflectionOnlyLoad(args.Name);
}

这有助于加载在其他程序集中定义的类型。

希望有帮助!


您将无法获取命名空间中的所有类型,因为命名空间可以桥接多个程序集,但可以获取程序集中的所有类,并检查它们是否属于该命名空间。

Assembly.GetTypes()在本地程序集上工作,或者您可以先加载一个程序集,然后在其上调用GetTypes()


仅在一行中按部分命名空间名称获取所有类:

1
var allClasses = Assembly.GetExecutingAssembly().GetTypes().Where(a => a.IsClass && a.Namespace != null && a.Namespace.Contains(@"..your namespace...")).ToList();

就像@aku answer,但是使用扩展方法:

1
2
3
4
5
6
7
string @namespace ="...";

var types = Assembly.GetExecutingAssembly().GetTypes()
    .Where(t => t.IsClass && t.Namespace == @namespace)
    .ToList();

types.ForEach(t => Console.WriteLine(t.Name));

名称空间实际上在运行时的设计中相当被动,主要用作组织工具。.NET中类型的全名由命名空间和class/enum/etc组合而成。如果只想遍历特定的程序集,只需遍历assembly.getexportedtypes()返回的类型,检查type.namespace的值。如果尝试遍历当前AppDomain中加载的所有程序集,则将涉及使用AppDomain.CurrentDomain.GetAssemblies()。


很简单

1
2
3
4
Type[] types = Assembly.Load(new AssemblyName("mynamespace.folder")).GetTypes();
foreach (var item in types)
{
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//a simple combined code snippet

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace MustHaveAttributes
{
  class Program
  {
    static void Main ( string[] args )
    {
      Console.WriteLine (" START" );

      // what is in the assembly
      Assembly a = Assembly.Load ("MustHaveAttributes" );
      Type[] types = a.GetTypes ();
      foreach (Type t in types)
      {

        Console.WriteLine ("Type is {0}", t );
      }
      Console.WriteLine (
        "{0} types found", types.Length );

      #region Linq
      //#region Action


      //string @namespace ="MustHaveAttributes";

      //var q = from t in Assembly.GetExecutingAssembly ().GetTypes ()
      //        where t.IsClass && t.Namespace == @namespace
      //        select t;
      //q.ToList ().ForEach ( t => Console.WriteLine ( t.Name ) );


      //#endregion Action  
      #endregion

      Console.ReadLine ();
      Console.WriteLine (" HIT A KEY TO EXIT" );
      Console.WriteLine (" END" );
    }
  } //eof Program


  class ClassOne
  {

  } //eof class

  class ClassTwo
  {

  } //eof class


  [System.AttributeUsage ( System.AttributeTargets.Class |
    System.AttributeTargets.Struct, AllowMultiple = true )]
  public class AttributeClass : System.Attribute
  {

    public string MustHaveDescription { get; set; }
    public string MusHaveVersion { get; set; }


    public AttributeClass ( string mustHaveDescription, string mustHaveVersion )
    {
      MustHaveDescription = mustHaveDescription;
      MusHaveVersion = mustHaveVersion;
    }

  } //eof class

} //eof namespace