Come si ottengono tutte le classi in uno spazio dei nomi tramite la riflessione in C #?
Il codice seguente stampa i nomi delle classi nel namespace
definito nell'assembly corrente.
Come altri ragazzi hanno sottolineato, uno spazio dei nomi può essere sparso tra i 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, puoi 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.
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);
}
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'Assemblea
Ecco una correzione per gli errori LoaderException che è probabile trovare se uno dei tipi sublass un tipo in un altro assieme:
// 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 sia d'aiuto!
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 puoi prima caricare un assembly, quindi chiamare GetTypes()
su di esso.
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 desideri solo passare attraverso un determinato assieme, esegui semplicemente il ciclo tra i tipi restituiti dall'Assemblea . GetExportedTypes () verifica il valore del 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
Abbastanza semplice
Type[] types = Assembly.Load(new AssemblyName("mynamespace.folder")).GetTypes();
foreach (var item in types)
{
}