【问题标题】:Getting all types in a namespace via reflection通过反射获取命名空间中的所有类型
【发布时间】:2010-09-09 22:20:42
【问题描述】:

如何通过 C# 中的反射获取命名空间中的所有类?

【问题讨论】:

  • 你能编辑你的问题吗...潜台词问题比“C#中的命名空间”更具交流性
  • 你可以看here。有 2 个不同的样本。

标签: c# .net reflection namespaces


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:
    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);
    }
    

    【讨论】:

    • 注意:您可以执行此操作,前提是您输入了要查找的程序集和 NS。类型可以在多个程序集中定义,属于同一个NS。
    • 我并不是要刻薄,但在这段代码中找到的所有项目都有一个完全不必要的列表和迭代; “classlist”变量和通过“namespacelist”的foreach提供的功能与返回“namespacelist”没有区别
    • @TheXenocide 代码示例的目的并不总是展示编写代码的“最佳”方式,而是清楚地传达某事是如何完成的。
    • 你使用两个列表和两次迭代的唯一帮助是让我放慢速度,试图弄清楚为什么你使用两个列表而不是在第一次迭代时直接添加到classlist asm.GetTypes() 结果。
    • 当您只有一个数据列表可以使用时,这里有两个列表是糟糕的代码。它不会使任何事情变得更清晰,并且会鼓励阅读它的初学者养成不良的编码习惯。
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      以下代码打印当前程序集中定义的指定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));
      

      【讨论】:

        【解决方案5】:

        很简单

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

        【讨论】:

        • 而且很简单地没有回答这个问题。所有这一切都是在单个程序集中获取所有类型的列表,而不考虑任何特定的命名空间。
        【解决方案6】:

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

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

        除非您想要其他域的类,否则这应该可以工作。要获取所有域的列表,请关注this link.

        【讨论】:

        • 工作正常 - 一个小提醒:我试图删除“&amp;&amp; t.Namespace == @namespace” - 这给了我所有 .net程序集:-)
        • @Netsi1964 如果您删除 &amp;&amp; t.Namespace == @namespace,您将获得 所有程序集 的所有 ,包括 .net 的。 GetAssemblies 将提供所有程序集,GetAssemblies().SelectMany(t =&gt; t.GetTypes()) 将提供所有程序集的所有类型(类、结构等)。
        • 我升级到 DotNet Core 2.2(从 2.1 开始)并且此代码停止对我的特定程序集工作。我想要的程序集没有在代码中的任何地方引用,所以没有加载! 2.1 已经加载了,但是 2.2 好像有延迟加载?
        • @Harvey .NET Core 是否有 appdomain 开头?
        • @nawfal 是的。此代码以前在 2.1 中有效。我发现我使用 Assembly.Load(nameof(NameOfMyNamespace)) 强制加载程序集工作得很好。
        【解决方案7】:

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

        Assembly.GetTypes() 作用于本地程序集,或者您可以先加载程序集,然后对其调用GetTypes()

        【讨论】:

        • +1 为正确答案。 AppDomain.CurrentDomain.GetAssemblies 可能会有所帮助。
        • ...然后循环遍历它们,过滤掉与命名空间不匹配的那些。
        • OP 专门要求“命名空间中的类”,而这会让您“在程序集中输入类型” - 所以这个答案是不完整的。正确答案可能是this one,它只枚举所有程序集中的类。
        【解决方案8】:

        就像@aku 回答,但使用扩展方法:

        string @namespace = "...";
        
        var types = Assembly.GetExecutingAssembly().GetTypes()
            .Where(t => t.IsClass && t.Namespace == @namespace)
            .ToList();
        
        types.ForEach(t => Console.WriteLine(t.Name));
        

        【讨论】:

          【解决方案9】:
          //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 到底是什么意思?我看不到任何与测试类是否具有属性有关的内容。这比有用更令人困惑。
          【解决方案10】:

          以下是针对 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 的代码更有帮助,也更少令人困惑。
          • 你确实也让我困惑了一段时间。我仍然只能猜测Assembly a 的东西代表了可能导致此事件触发的正常处理。我认为 a 在帮助解决 LoaderException 错误方面没有用。我说的对吗?
          【解决方案11】:

          命名空间在运行时的设计中实际上是相当被动的,主要用作组织工具。 .NET 中类型的全名由命名空间和类/枚举/等组成。结合。如果您只想通过特定的程序集,您只需循环通过程序集返回的类型。GetExportedTypes() 检查类型的值。Namespace。如果您尝试浏览当前 AppDomain 中加载的所有程序集,则需要使用 AppDomain.CurrentDomain.GetAssemblies()

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-01-26
            • 2020-11-01
            • 2014-01-29
            • 1970-01-01
            • 2013-04-02
            • 2010-10-31
            相关资源
            最近更新 更多