web-dev-qa-db-fra.com

Obtenir tous les types dans un espace de noms via réflexion

Comment obtenir toutes les classes d'un espace de noms par réflexion en C #?

245
Chethan

Le code suivant imprime les noms des classes dans la variable namespace définie dans l’Assemblée actuelle.
Comme l'ont souligné d'autres personnes, un espace de noms peut être dispersé entre différents modules. Vous devez donc d'abord obtenir une liste des assemblys.

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

Comme le dit FlySwat, vous pouvez avoir le même espace de noms couvrant plusieurs assemblys (par exemple, System.Collections.Generic). Vous devrez charger tous ces assemblys s'ils ne sont pas déjà chargés. Donc pour une réponse complète:

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

Cela devrait fonctionner sauf si vous voulez des classes d'autres domaines. Pour obtenir la liste de tous les domaines, suivez ce lien.

69
nawfal
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;
}

NB: Le code ci-dessus illustre ce qui se passe. Si vous deviez l'implémenter, une version simplifiée peut être utilisée:

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);
}
22
Ryan Farley

Pour un assembly spécifique, NameSpace et 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();

Remarque: le projet doit référencer l’Assemblée.

15
John Peters

Voici un correctif pour les erreurs LoaderException que vous trouverez probablement si l'un des types sous-classe un type dans un autre assembly:

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

Cela devrait aider avec les types de chargement définis dans d'autres assemblys.

J'espère que ça t'as aidé!

12
tsimon

Vous ne pourrez pas obtenir tous les types dans un espace-noms, car un espace-noms peut relier plusieurs assemblys, mais vous pouvez obtenir toutes les classes dans un assemblage et vérifier s'ils appartiennent à cet espace-noms.

Assembly.GetTypes() fonctionne sur l'assemblage local ou vous pouvez d'abord charger un assemblage, puis appeler GetTypes().

9
FlySwat

Tout comme @aku answer, mais en utilisant des méthodes d'extension:

string @namespace = "...";

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

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

Obtenez toutes les classes par partie du nom d'espace de nom dans une seule ligne:

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

Les espaces de noms sont en réalité plutôt passifs dans la conception du moteur d'exécution et servent principalement d'outils d'organisation. Le nom complet d'un type dans .NET est constitué de l'espace de noms et de la classe/énumération/etc. combiné. Si vous souhaitez uniquement parcourir un assemblage spécifique, il vous suffit de parcourir les types renvoyés par Assembly . GetExportedTypes () en vérifiant la valeur du type . Namespace . Si vous tentiez de parcourir tous les assemblys chargés dans le AppDomain actuel, vous utiliseriez AppDomain.CurrentDomain . GetAssemblies ()

3
TheXenocide
//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 
2
Yordan Georgiev

Assez facile

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