Come si ottengono tutte le classi in uno spazio dei nomi tramite la riflessione in C #?
Come si ottengono tutte le classi in uno spazio dei nomi tramite la riflessione in C #?
Risposte:
Il codice seguente stampa i nomi delle classi specificate namespace
nell'assembly corrente.
Come altri ragazzi hanno sottolineato, uno spazio dei nomi può essere distribuito tra diversi moduli, quindi è necessario prima ottenere un elenco di assiemi.
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));
Come dice FlySwat, è possibile avere lo stesso spazio dei nomi che si estende in più assiemi (ad esempio System.Collections.Generic
). Dovrai caricare tutti quegli assembly se non sono già stati caricati. Quindi per una risposta completa:
AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(t => t.GetTypes())
.Where(t => t.IsClass && t.Namespace == @namespace)
Questo dovrebbe funzionare a meno che tu non voglia classi di altri domini. Per ottenere un elenco di tutti i domini, segui questo link.
&& t.Namespace == @namespace
" - che spesso mi ha dato tutti gli assembly .net :-)
&& t.Namespace == @namespace
ottieni tutte le classi di tutti gli assembly , inclusi quelli di .net. GetAssemblies
ti darà tutti gli assembly e GetAssemblies().SelectMany(t => t.GetTypes())
ti darà tutti i tipi (classi, strutture ecc.) di tutti gli assembly.
Assembly.Load(nameof(NameOfMyNamespace))
funzionava perfettamente.
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: il codice sopra mostra cosa sta succedendo. Se lo si implementasse, è possibile utilizzare una versione semplificata:
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
prima iterazione sul asm.GetTypes()
risultato.
Per uno specifico Assembly, NameSpace e 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();
Nota: il progetto deve fare riferimento all'assemblaggio
Ecco una correzione per gli errori LoaderException che probabilmente troverai se uno dei tipi sublass un tipo in un altro 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);
}
Ciò dovrebbe aiutare con i tipi di caricamento definiti in altri assiemi.
Spero che aiuti!
Assembly a
roba rappresenti la normale elaborazione che potrebbe causare il verificarsi di questo evento. Non vedo alcuna utilità a
nell'aiutare con LoaderException
errori. Ho ragione?
Non sarai in grado di ottenere tutti i tipi in uno spazio dei nomi, perché uno spazio dei nomi può collegare più assembly, ma puoi ottenere tutte le classi in un assembly e verificare se appartengono a quello spazio dei nomi.
Assembly.GetTypes()
funziona sull'assembly locale oppure è possibile caricare prima un assembly, quindi richiamarlo GetTypes()
.
AppDomain.CurrentDomain.GetAssemblies
può essere d'aiuto.
Proprio come la risposta di @aku, ma usando i metodi di estensione:
string @namespace = "...";
var types = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.IsClass && t.Namespace == @namespace)
.ToList();
types.ForEach(t => Console.WriteLine(t.Name));
Ottieni tutte le classi per parte del nome dello spazio dei nomi in una sola riga:
var allClasses = Assembly.GetExecutingAssembly().GetTypes().Where(a => a.IsClass && a.Namespace != null && a.Namespace.Contains(@"..your namespace...")).ToList();
Gli spazi dei nomi sono in realtà piuttosto passivi nella progettazione del runtime e servono principalmente come strumenti organizzativi. Il nome completo di un tipo in .NET è costituito dallo spazio dei nomi e da Class / Enum / Etc. combinato. Se si desidera solo passare attraverso un assembly specifico, è sufficiente scorrere i tipi restituiti dall'assembly. GetExportedTypes () verifica il valore di tipo. Namespace . Se si stesse tentando di esaminare tutti gli assembly caricati nell'AppDomain corrente, ciò implica l'utilizzo di 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
il nome MustHaveAttributes
? Non vedo nulla relativo al test se una classe ha attributi o meno. Questo è più confuso che utile.
Abbastanza semplice
Type[] types = Assembly.Load(new AssemblyName("mynamespace.folder")).GetTypes();
foreach (var item in types)
{
}