通过反射获取名称空间中的所有类型


Answers:


316

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

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

83

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

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

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


1
工作正常-一个小提醒:我试图删除“ && t.Namespace == @namespace”-这是因为它给了我所有 .net程序集:-)
Netsi1964

@ Netsi1964如果去掉&& t.Namespace == @namespace你得到所有类别所有组件,包括.NET的。GetAssemblies将为您提供所有程序集,并提供所有程序集的GetAssemblies().SelectMany(t => t.GetTypes())所有类型(类,结构等)。
nawfal 2014年

我从2.1升级到DotNet Core 2.2(该代码),该代码停止了我的特定程序集的工作。我想要的程序集未在代码中的任何地方引用,因此未加载!在2.1中已加载,但2.2似乎有延迟加载?
哈维

@Harvey .NET Core是否首先具有appdomain?
nawfal

@nawfal是的。该代码以前在2.1中起作用。我发现我通过使用Assembly.Load(nameof(NameOfMyNamespace))工作正常来强制加载程序集。
哈维

28
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;
}

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

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

9
我并不是要刻薄,但是在此代码中,所有找到的项都有一个完全不必要的列表和迭代;“ classlist”变量和通过“ namespacelist”的foreach提供的功能与返回“ namespacelist”的功能相同
TheXenocide 08/09/19

10
@TheXenocide代码示例的目的并不总是要表示“最佳”编写代码的方式,而是要清楚地传达出完成工作的方式。
瑞安·法利

4
我只是为了教育而指出。让物质上的人从我们能做到的最好的榜样中学习是我们的责任,而不是冒险冒一个不利于理解的坏榜样。我并不是说这特别有害,但是我不同意这种观点
TheXenocide

4
如果对所提出的问题没有帮助,我将回答否定。将鼠标悬停在向上/向下投票按钮上时,您会看到提示:“这很有帮助”。对我来说,决定是否进行投票是决定是否有助于回答所提出的问题。
瑞安·法利

3
使用两个列表和两个迭代的唯一帮助是拖慢了我的速度,试图弄清楚为什么使用两个列表,而不是直接classlist在第一次迭代中添加asm.GetTypes()结果。
ProfK 2014年

20

对于特定的程序集,NameSpace和ClassName:

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

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


12

这是针对LoaderException错误的修复程序,您可能会发现其中一种类型在另一个程序集中对某个类型进行了子类化:

// 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);
}

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

希望有帮助!


当然,即使不考虑它,也比Ryan Farley的代码看起来很有帮助,并且没有那么有用,也更少混乱。
ProfK 2014年

你也确实让我困惑了一段时间。我仍然只能猜测,这些Assembly a东西代表了可能导致此事件触发的正常处理。我认为a无助于解决LoaderException错误。我对吗?
ProfK 2014年

9

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

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


2
+1为正确答案。AppDomain.CurrentDomain.GetAssemblies会有所帮助。
2013年

...然后遍历它们,筛选出与名称空间不匹配的内容。
TJ Crowder

OP专门要求“名称空间中的类”,而这使您“在程序集中键入”-因此此答案不完整。正确的答案可能是这个,它仅枚举所有程序集中的类。
mindplay.dk

6

就像@aku答案一样,但是使用扩展方法:

string @namespace = "...";

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

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

5

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

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

3

命名空间实际上在运行时的设计中是被动的,并且主要用作组织工具。.NET中类型的全名由命名空间和Class / Enum / Etc组成。结合。如果只希望通过特定的程序集,则只需循环遍历程序集返回的类型。GetExportedTypes()检查类型的值。命名空间。如果尝试遍历当前AppDomain中加载的所有程序集,则将涉及使用AppDomain.CurrentDomain。GetAssemblies()


2
//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 

到底叫什么AttributeClass名字MustHaveAttributes?我没有看到任何有关测试类是否具有属性的信息。这比帮助更令人困惑。
ProfK 2014年

1

非常简单

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

而且非常简单地不回答这个问题。这一切都是在单个程序集中获取所有类型的列表,而不管任何特定的名称空间如何。
伊恩
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.