pouvez-vous modifier votre question ... la question du sous-texte est plus communicative que l '' espace de noms en C # '
Gishu
Vous pouvez regarder ici . Il existe 2 échantillons différents.
Fatih GÜRDAL
Réponses:
317
Le code suivant imprime les noms des classes spécifiées namespacedéfinies dans l'assembly actuel.
Comme d'autres gars l'ont souligné, un espace de noms peut être dispersé entre différents modules, vous devez donc d'abord obtenir une liste des assemblys.
Comme FlySwat le dit, vous pouvez avoir le même espace de noms couvrant plusieurs assemblages (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:
fonctionne bien - un petit rappel: j'ai essayé de supprimer " && t.Namespace == @namespace" - ce qui m'a donné tous les assemblages .net :-)
Netsi1964
@ Netsi1964 si vous supprimez, && t.Namespace == @namespacevous obtenez toutes les classes de tous les assemblys , y compris les .net. GetAssembliesvous donnera tous les assemblys et GetAssemblies().SelectMany(t => t.GetTypes())donnera tous les types (classes, structures, etc.) de tous les assemblys.
nawfal
J'ai mis à niveau vers DotNet Core 2.2 (à partir de 2.1) et ce code a cessé de fonctionner pour mon assemblage spécifique. L'assembly que je voulais n'était référencé nulle part dans le code et n'était donc pas chargé! En 2.1, il était chargé, mais 2.2 semble avoir un chargement paresseux?
Harvey
@Harvey .NET Core a-t-il un domaine d'application pour commencer?
nawfal
@nawfal Ouais. Ce code fonctionnait précédemment en 2.1. J'ai trouvé que je force le chargement d'un assemblage en utilisant très bien Assembly.Load(nameof(NameOfMyNamespace))travaillé.
Harvey
28
using System.Reflection;
using System.Collections.Generic;//...staticList<string>GetClasses(string nameSpace){Assembly asm =Assembly.GetExecutingAssembly();List<string> namespacelist =newList<string>();List<string> classlist =newList<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 l'implémentiez, une version simplifiée peut être utilisée:
using System.Linq;
using System.Reflection;
using System.Collections.Generic;//...staticIEnumerable<string>GetClasses(string nameSpace){Assembly asm =Assembly.GetExecutingAssembly();return asm.GetTypes().Where(type => type.Namespace== nameSpace).Select(type => type.Name);}
Je n'essaie pas d'être méchant, mais il y a une liste et une itération entièrement inutiles à travers tous les éléments trouvés dans ce code; la variable "classlist" et foreach via "namespacelist" ne fournissent aucune fonctionnalité différente du retour de "namespacelist"
TheXenocide
10
@TheXenocide l'objectif d'un exemple de code n'est pas toujours destiné à montrer la "meilleure" façon d'écrire du code, mais à expliquer clairement comment quelque chose est fait.
Ryan Farley
4
Je le faisais simplement remarquer pour le bien de l'éducation; c'est notre responsabilité de faire en sorte que les gens apprennent du meilleur exemple possible plutôt que de risquer un mauvais exemple qui influence négativement la compréhension. Je ne dis pas que cela en particulier est préjudiciable, mais je ne suis pas d'accord avec le sentiment
TheXenocide
4
Je vote contre une réponse si elle n'est pas utile à la question qui a été posée. L'astuce que vous voyez lorsque vous survolez le bouton de vote haut / bas indique "Cela a été utile". La décision de voter pour / contre une réponse, pour moi, est de savoir si cela a été utile ou non pour répondre à la question posée.
Ryan Farley
3
La seule chose que vous avez utilisée en utilisant deux listes et deux itérations a aidé à me ralentir en essayant de comprendre pourquoi vous avez utilisé deux listes et ne vous êtes pas contenté d'ajouter directement à classlistla première itération du asm.GetTypes()résultat.
ProfK
20
Pour un assembly, un espace de nom et un nom de classe spécifiques:
Voici un correctif pour les erreurs LoaderException que vous êtes susceptible de trouver si l'un des types sous-classe un type dans un autre assembly:
// Setup event handler to resolve assembliesAppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve+=newResolveEventHandler(CurrentDomain_ReflectionOnlyAssemblyResolve);Assembly a =System.Reflection.Assembly.ReflectionOnlyLoadFrom(filename);
a.GetTypes();// process types here// method later in the class:staticAssemblyCurrentDomain_ReflectionOnlyAssemblyResolve(object sender,ResolveEventArgs args){returnSystem.Reflection.Assembly.ReflectionOnlyLoad(args.Name);}
Cela devrait aider à charger les types définis dans d'autres assemblys.
Bien sûr, cela semble utile, et moins plus utile et moins déroutant que le code de Ryan Farley, même sans y penser.
ProfK
Mais vous m'avez aussi confus pendant un certain temps. Je ne peux que deviner que la Assembly asubstance représente le traitement normal qui pourrait provoquer le déclenchement de cet événement. Je ne vois aucune utilité pour aaider à LoaderExceptionrésoudre les erreurs. Ai-je raison?
ProfK
9
Vous ne pourrez pas obtenir tous les types dans un espace de noms, car un espace de noms peut relier plusieurs assemblys, mais vous pouvez obtenir toutes les classes dans un assemblage et vérifier si elles appartiennent à cet espace de noms.
Assembly.GetTypes()fonctionne sur l'assembly local, ou vous pouvez d'abord charger un assembly puis l'appeler GetTypes().
+1 pour la bonne réponse. AppDomain.CurrentDomain.GetAssembliespeut être utile.
nawfal
... puis parcourez-les, en filtrant ceux qui ne correspondent pas à l'espace de noms.
TJ Crowder
OP a spécifiquement demandé des "classes dans un espace de noms", alors que cela vous permet de "taper dans un assembly" - donc cette réponse est incomplète. La bonne réponse est probablement celle-ci , qui énumère uniquement les classes, de tous les assemblys.
mindplay.dk
6
Tout comme la réponse @aku, mais en utilisant des méthodes d'extension:
Les espaces de noms sont en fait plutôt passifs dans la conception du runtime et servent principalement d'outils d'organisation. Le nom complet d'un type dans .NET se compose de l'espace de noms et de Class / Enum / Etc. combiné. Si vous souhaitez uniquement passer par un assembly spécifique, vous devez simplement parcourir les types renvoyés par assembly. GetExportedTypes () vérifiant la valeur de type. Espace de noms . Si vous tentiez de parcourir tous les assemblys chargés dans l'AppDomain actuel, cela impliquerait d'utiliser AppDomain.CurrentDomain. GetAssemblies ()
//a simple combined code snippet
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace MustHaveAttributes{classProgram{staticvoidMain(string[] args ){Console.WriteLine(" START ");// what is in the assemblyAssembly 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 #endregionConsole.ReadLine();Console.WriteLine(" HIT A KEY TO EXIT ");Console.WriteLine(" END ");}}//eof ProgramclassClassOne{}//eof class classClassTwo{}//eof class[System.AttributeUsage(System.AttributeTargets.Class|System.AttributeTargets.Struct,AllowMultiple=true)]publicclassAttributeClass:System.Attribute{publicstringMustHaveDescription{get;set;}publicstringMusHaveVersion{get;set;}publicAttributeClass(string mustHaveDescription,string mustHaveVersion ){MustHaveDescription= mustHaveDescription;MusHaveVersion= mustHaveVersion;}}//eof class }//eof namespace
Quel est AttributeClassle nom MustHaveAttributes? Je ne vois rien concernant le test si une classe a des attributs ou non. C'est plus déroutant qu'utile.
ProfK
1
Assez facile
Type[] types =Assembly.Load(newAssemblyName("mynamespace.folder")).GetTypes();foreach(var item in types){}
Et tout simplement ne pas répondre à la question. Tout cela consiste à obtenir une liste de tous les types dans un seul assembly, indépendamment de tout espace de noms particulier.
Réponses:
Le code suivant imprime les noms des classes spécifiées
namespace
définies dans l'assembly actuel.Comme d'autres gars l'ont souligné, un espace de noms peut être dispersé entre différents modules, vous devez donc d'abord obtenir une liste des assemblys.
la source
Comme FlySwat le dit, vous pouvez avoir le même espace de noms couvrant plusieurs assemblages (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:Cela devrait fonctionner, sauf si vous voulez des classes d'autres domaines. Pour obtenir une liste de tous les domaines, suivez ce lien.
la source
&& t.Namespace == @namespace
" - ce qui m'a donné tous les assemblages .net :-)&& t.Namespace == @namespace
vous obtenez toutes les classes de tous les assemblys , y compris les .net.GetAssemblies
vous donnera tous les assemblys etGetAssemblies().SelectMany(t => t.GetTypes())
donnera tous les types (classes, structures, etc.) de tous les assemblys.Assembly.Load(nameof(NameOfMyNamespace))
travaillé.NB: Le code ci-dessus illustre ce qui se passe. Si vous l'implémentiez, une version simplifiée peut être utilisée:
la source
classlist
la première itération duasm.GetTypes()
résultat.Pour un assembly, un espace de nom et un nom de classe spécifiques:
Remarque: Le projet doit référencer l'assemblage
la source
Voici un correctif pour les erreurs LoaderException que vous êtes susceptible de trouver si l'un des types sous-classe un type dans un autre assembly:
Cela devrait aider à charger les types définis dans d'autres assemblys.
J'espère que cela pourra aider!
la source
Assembly a
substance représente le traitement normal qui pourrait provoquer le déclenchement de cet événement. Je ne vois aucune utilité poura
aider àLoaderException
résoudre les erreurs. Ai-je raison?Vous ne pourrez pas obtenir tous les types dans un espace de noms, car un espace de noms peut relier plusieurs assemblys, mais vous pouvez obtenir toutes les classes dans un assemblage et vérifier si elles appartiennent à cet espace de noms.
Assembly.GetTypes()
fonctionne sur l'assembly local, ou vous pouvez d'abord charger un assembly puis l'appelerGetTypes()
.la source
AppDomain.CurrentDomain.GetAssemblies
peut être utile.Tout comme la réponse @aku, mais en utilisant des méthodes d'extension:
la source
Obtenez toutes les classes par partie du nom de l'espace de noms sur une seule ligne:
la source
Les espaces de noms sont en fait plutôt passifs dans la conception du runtime et servent principalement d'outils d'organisation. Le nom complet d'un type dans .NET se compose de l'espace de noms et de Class / Enum / Etc. combiné. Si vous souhaitez uniquement passer par un assembly spécifique, vous devez simplement parcourir les types renvoyés par assembly. GetExportedTypes () vérifiant la valeur de type. Espace de noms . Si vous tentiez de parcourir tous les assemblys chargés dans l'AppDomain actuel, cela impliquerait d'utiliser AppDomain.CurrentDomain. GetAssemblies ()
la source
la source
AttributeClass
le nomMustHaveAttributes
? Je ne vois rien concernant le test si une classe a des attributs ou non. C'est plus déroutant qu'utile.Assez facile
la source