2008-09-17 7 views
212

Comment obtenir toutes les classes d'un espace de nom par réflexion en C#?Obtention de tous les types dans un espace de nom par réflexion

+0

pouvez-vous éditer votre question ... la question de sous-texte est un plus communicatif que le 'Namespace en C#' – Gishu

+0

Vous pouvez regarder [ici] (http: // stackoverflow.com/questions/949246/comment-obtenir-toutes-classes-dans-namespace). Il y a 2 échantillons différents. –

Répondre

18
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; 
} 
+0

Remarque: Vous pouvez le faire à condition de saisir l'assemblage et le NS à rechercher. Les types peuvent être définis dans plusieurs assemblages et appartiennent à la même NS. – Gishu

+0

C'est vrai Gishu. Je suppose qu'il serait préférable de passer l'assembly ainsi que l'espace de noms de l'assembly que vous voulez supprimer l'ambiguïté. –

+1

"namespace" - mot-clé réservé, vous devez ajouter @ préfixe pour faire compiler ce code – aku

9

Vous ne serez pas en mesure d'obtenir tous les types dans un espace de noms, car un espace de noms peut combler plusieurs ensembles, mais vous pouvez obtenir toutes les classes dans un ensemble et vérifier si elles appartiennent à cet espace de noms.

Assembly.GetTypes() fonctionne sur l'assembly local, ou vous pouvez charger un assembly en premier, puis appeler le GetTypes() dessus.

+1

+1 pour la bonne réponse. 'AppDomain.CurrentDomain.GetAssemblies' peut être utile. – nawfal

+0

... puis passez en boucle, en filtrant ceux qui ne correspondent pas à l'espace de noms. –

270

Le code suivant affiche les noms des classes définies dans l'assembly en cours namespace.
Comme d'autres personnes l'ont souligné, un espace de noms peut être dispersé entre différents modules, vous devez donc d'abord obtenir une liste des assemblages.

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

Les espaces de noms sont plutôt passifs dans la conception de l'environnement d'exécution et servent principalement d'outils d'organisation. Le nom complet d'un type dans .NET se compose de l'espace de noms et de la classe/Enum/Etc. combiné. Si vous souhaitez uniquement passer par un assemblage spécifique, vous devez simplement parcourir les types renvoyés par assembly. GetExportedTypes() en vérifiant la valeur du type. Namespace. Si vous essayez de parcourir tous les assemblys chargés dans l'AppDomain actuel, cela impliquera d'utiliser AppDomain.CurrentDomain. GetAssemblies()

12

est ici un correctif pour les erreurs de LoaderException que vous êtes susceptible de trouver si l'un des types sublasses un type dans un autre ensemble:

// 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 charge définis dans d'autres assemblées.

Espérons que ça aide!

+0

Sure semble utile, et moins utile et moins déroutant que le code de Ryan Farley, même sans y penser. – ProfK

+0

Vous m'avez aussi confus pendant un moment cependant. Je ne peux toujours que deviner que l'élément 'Assembly a' représente le traitement normal qui pourrait déclencher cet événement. Je ne vois aucune utilité pour 'a' en aidant les erreurs' LoaderException'. Ai-je raison? – ProfK

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 
+0

Qu'est ce que'AttributeClass' le nom 'MustHaveAttributes'? Je ne vois rien concernant le fait de tester si une classe a des attributs ou non. C'est plus déroutant qu'utile. – ProfK

5

Comme réponse @aku, 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)); 
60

Comme le dit FlySwat, vous pouvez avoir le même espace couvrant dans plusieurs ensembles (pour par exemple System.Collections.Generic). Vous devrez charger tous ces assemblages 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 une liste de tous les domaines, suivez this link.

+1

fonctionne très bien - un petit rappel: j'ai essayé d'enlever "' && t.Namespace == @ namespace' "- qui m'a souvent donné ** tous les ** assemblages .net :-) – Netsi1964

+0

@ Netsi1964 si vous supprimez' && t.Espace de nommage == @ namespace' vous obtenez toutes les * classes * de * tous les assemblages *, y compris les .net. 'GetAssemblies' vous donnera tous les assemblys, et' GetAssemblies(). SelectMany (t => t.GetTypes()) 'donnera tous les types (classes, structures etc) de tous les assemblys. – nawfal

2

Obtenez toutes les classes par une partie du nom Namespace en une seule ligne:

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

Pour une assemblée spécifique, avec un filtre de nom de classe:

var asm = Assembly.Load("Some.Assembly.Name"); 
var nameSpace = "Some.Namespace.Name"; 

var classes = asm.GetTypes().Where(p => 
    p.Namespace == nameSpace && 
    p.Name.Contains("ClassNameFilter") 
).ToList(); 

note: le projet doit faire référence à l'ensemble

2

est très simple

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