Jak uzyskać wszystkie klasy w przestrzeni nazw poprzez odbicie w C #?
Jak uzyskać wszystkie klasy w przestrzeni nazw poprzez odbicie w C #?
Odpowiedzi:
Poniższy kod wyświetla nazwy klas w określonym namespace
zdefiniowanym w bieżącym zestawie.
Jak zauważyli inni faceci, przestrzeń nazw może być rozproszona między różnymi modułami, więc najpierw musisz uzyskać listę zestawów.
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));
Jak mówi FlySwat, możesz mieć tę samą przestrzeń nazw obejmującą wiele zestawów (na przykład System.Collections.Generic
). Będziesz musiał załadować wszystkie te zespoły, jeśli jeszcze nie zostały załadowane. Aby uzyskać pełną odpowiedź:
AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(t => t.GetTypes())
.Where(t => t.IsClass && t.Namespace == @namespace)
Powinno to działać, chyba że chcesz klas innych domen. Aby uzyskać listę wszystkich domen, kliknij ten link.
&& t.Namespace == @namespace
” - co z tego powodu dało mi wszystkie zestawy .net :-)
&& t.Namespace == @namespace
można uzyskać wszystkie zajęcia z wszystkich zespołów , w tym .NET jest. GetAssemblies
da ci wszystkie zespoły i GetAssemblies().SelectMany(t => t.GetTypes())
da wszystkie typy (klasy, struktury itp.) ze wszystkich zespołów.
Assembly.Load(nameof(NameOfMyNamespace))
dobrze działającego.
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: Powyższy kod ilustruje, co się dzieje. Gdybyś go wdrożył, możesz użyć uproszczonej wersji:
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
po pierwszej iteracji nad asm.GetTypes()
wynikiem.
Dla konkretnego zestawu, NameSpace i 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();
Uwaga: Projekt musi odwoływać się do zestawu
Oto poprawka błędów LoaderException, które prawdopodobnie znajdziesz, jeśli jeden z typów podklasuje typ w innym zestawie:
// 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);
}
To powinno pomóc w ładowaniu typów zdefiniowanych w innych złożeniach.
Mam nadzieję, że to pomaga!
Assembly a
reprezentują normalne przetwarzanie, które może spowodować uruchomienie tego zdarzenia. Nie widzę sensu a
w pomaganiu w LoaderException
błędach. Czy mam rację?
Nie będziesz w stanie uzyskać wszystkich typów w przestrzeni nazw, ponieważ przestrzeń nazw może łączyć wiele zestawów, ale możesz zebrać wszystkie klasy w zestawie i sprawdzić, czy należą one do tego obszaru nazw.
Assembly.GetTypes()
działa na lokalnym zespole lub możesz najpierw załadować zespół, a następnie go wywołać GetTypes()
.
AppDomain.CurrentDomain.GetAssemblies
może być pomocny.
Podobnie jak odpowiedź @aku, ale przy użyciu metod rozszerzenia:
string @namespace = "...";
var types = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.IsClass && t.Namespace == @namespace)
.ToList();
types.ForEach(t => Console.WriteLine(t.Name));
Uzyskaj wszystkie klasy według części nazwy Przestrzeni nazw w jednym wierszu:
var allClasses = Assembly.GetExecutingAssembly().GetTypes().Where(a => a.IsClass && a.Namespace != null && a.Namespace.Contains(@"..your namespace...")).ToList();
Przestrzenie nazw są w rzeczywistości raczej pasywne w projektowaniu środowiska wykonawczego i służą przede wszystkim jako narzędzia organizacyjne. Pełna nazwa typu w .NET składa się z przestrzeni nazw i Class / Enum / Etc. łączny. Jeśli chcesz przejść tylko przez określony zestaw, po prostu przejrzyj typy zwrócone przez zestaw. GetExportedTypes () sprawdza wartość typu. Nazw . Jeśli próbujesz przejść przez wszystkie zestawy załadowane w bieżącej AppDomain, wymagałoby to użycia 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
nazwa MustHaveAttributes
? Nie widzę nic związanego z testowaniem, czy klasa ma atrybuty, czy nie. Jest to bardziej mylące niż pomocne.
Całkiem proste
Type[] types = Assembly.Load(new AssemblyName("mynamespace.folder")).GetTypes();
foreach (var item in types)
{
}