Comment obtenez-vous toutes les classes dans un espace de noms grâce à la réflexion en C #?
Comment obtenez-vous toutes les classes dans un espace de noms grâce à la réflexion en C #?
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.
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));
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:
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 ce lien.
&& 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 et GetAssemblies().SelectMany(t => t.GetTypes())
donnera tous les types (classes, structures, etc.) de tous les assemblys.
Assembly.Load(nameof(NameOfMyNamespace))
travaillé.
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 l'implémentiez, 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);
}
classlist
la première itération du asm.GetTypes()
résultat.
Pour un assembly, un espace de nom et un nom de classe spécifiques:
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'assemblage
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 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 à charger les types définis dans d'autres assemblys.
J'espère que cela pourra aider!
Assembly a
substance représente le traitement normal qui pourrait provoquer le déclenchement de cet événement. Je ne vois aucune utilité pour a
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'appeler GetTypes()
.
AppDomain.CurrentDomain.GetAssemblies
peut être utile.
Tout comme la 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));
Obtenez toutes les classes par partie du nom de l'espace de noms sur une seule ligne:
var allClasses = Assembly.GetExecutingAssembly().GetTypes().Where(a => a.IsClass && a.Namespace != null && a.Namespace.Contains(@"..your namespace...")).ToList();
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
{
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
le nom MustHaveAttributes
? Je ne vois rien concernant le test si une classe a des attributs ou non. C'est plus déroutant qu'utile.
Assez facile
Type[] types = Assembly.Load(new AssemblyName("mynamespace.folder")).GetTypes();
foreach (var item in types)
{
}