Wie erhalten Sie alle Klassen in einem Namespace durch Reflektion in C #?
Wie erhalten Sie alle Klassen in einem Namespace durch Reflektion in C #?
Antworten:
Der folgende Code druckt Namen von Klassen in der angegebenen namespace
aktuellen Assembly.
Wie andere Leute betonten, kann ein Namespace auf verschiedene Module verteilt sein, daher müssen Sie zuerst eine Liste der Assemblys abrufen.
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));
Wie FlySwat sagt, können Sie denselben Namespace in mehreren Assemblys (z System.Collections.Generic
. B. ) verwenden. Sie müssen alle diese Assemblys laden, wenn sie noch nicht geladen sind. Für eine vollständige Antwort:
AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(t => t.GetTypes())
.Where(t => t.IsClass && t.Namespace == @namespace)
Dies sollte funktionieren, es sei denn, Sie möchten Klassen anderer Domänen. Folgen Sie diesem Link, um eine Liste aller Domains zu erhalten .
&& t.Namespace == @namespace
" zu entfernen - was mir natürlich alle .net-Assemblys gab :-)
&& t.Namespace == @namespace
Sie alle bekommen Klassen von allen Baugruppen , .net ist inklusive. GetAssemblies
gibt Ihnen alle Assemblys und GetAssemblies().SelectMany(t => t.GetTypes())
gibt alle Typen (Klassen, Strukturen usw.) aus allen Assemblys an.
Assembly.Load(nameof(NameOfMyNamespace))
funktioniere.
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: Der obige Code zeigt, was los ist. Wenn Sie es implementieren, kann eine vereinfachte Version verwendet werden:
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
bei der ersten Iteration über das asm.GetTypes()
Ergebnis direkt hinzugefügt haben .
Für eine bestimmte Assembly, NameSpace und 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();
Hinweis: Das Projekt muss auf die Baugruppe verweisen
Hier ist eine Korrektur für LoaderException-Fehler, die Sie wahrscheinlich finden, wenn einer der Typen einen Typ in einer anderen Assembly unterverteilt:
// 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);
}
Dies sollte beim Laden von Typen helfen, die in anderen Baugruppen definiert sind.
Ich hoffe, das hilft!
Assembly a
Zeug die normale Verarbeitung darstellt, die dieses Ereignis auslösen könnte. Ich sehe keinen a
Sinn darin, bei LoaderException
Fehlern zu helfen . Habe ich recht?
Sie können nicht alle Typen in einem Namespace abrufen, da ein Namespace mehrere Assemblys überbrücken kann. Sie können jedoch alle Klassen in einer Assembly abrufen und prüfen, ob sie zu diesem Namespace gehören.
Assembly.GetTypes()
funktioniert auf der lokalen Assembly, oder Sie können zuerst eine Assembly laden und dann aufrufen GetTypes()
.
AppDomain.CurrentDomain.GetAssemblies
kann hilfreich sein.
Genau wie @aku Antwort, aber mit Erweiterungsmethoden:
string @namespace = "...";
var types = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.IsClass && t.Namespace == @namespace)
.ToList();
types.ForEach(t => Console.WriteLine(t.Name));
Holen Sie sich alle Klassen nach einem Teil des Namespace-Namens in nur einer Zeile:
var allClasses = Assembly.GetExecutingAssembly().GetTypes().Where(a => a.IsClass && a.Namespace != null && a.Namespace.Contains(@"..your namespace...")).ToList();
Namespaces sind im Design der Laufzeit eigentlich eher passiv und dienen in erster Linie als organisatorische Werkzeuge. Der vollständige Name eines Typs in .NET besteht aus dem Namespace und Class / Enum / Etc. kombiniert. Wenn Sie nur eine bestimmte Baugruppe durchlaufen möchten, durchlaufen Sie einfach die von der Baugruppe zurückgegebenen Typen. GetExportedTypes () überprüft den Wert des Typs. Namespace . Wenn Sie versuchen würden, alle in der aktuellen AppDomain geladenen Assemblys durchzugehen, müssten Sie AppDomain.CurrentDomain verwenden. 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
dem Namen MustHaveAttributes
? Ich sehe nichts in Bezug auf das Testen, ob eine Klasse Attribute hat oder nicht. Das ist eher verwirrend als hilfreich.
Ziemlich einfach
Type[] types = Assembly.Load(new AssemblyName("mynamespace.folder")).GetTypes();
foreach (var item in types)
{
}