Poniższy kod wyświetla nazwy klas w określonym namespacezdefiniowanym 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.
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ź:
działa dobrze - małe przypomnienie: Próbowałem usunąć „ && t.Namespace == @namespace” - co z tego powodu dało mi wszystkie zestawy .net :-)
Netsi1964
@ Netsi1964 jeśli usunąć && t.Namespace == @namespacemożna uzyskać wszystkie zajęcia z wszystkich zespołów , w tym .NET jest. GetAssembliesda ci wszystkie zespoły i GetAssemblies().SelectMany(t => t.GetTypes())da wszystkie typy (klasy, struktury itp.) ze wszystkich zespołów.
nawfal
Uaktualniłem do DotNet Core 2.2 (od 2.1) i ten kod przestał działać dla mojego konkretnego zestawu. Żądany zestaw nie był w żadnym miejscu w kodzie, więc nie został załadowany! W 2.1 został załadowany, ale 2.2 wydaje się mieć opóźnione ładowanie?
Harvey
@Harvey Czy .NET Core ma na początku domenę?
nawfal
@nawfal Tak. Ten kod działał wcześniej w 2.1. Stwierdziłem, że wymuszam ładowanie zestawu za pomocą Assembly.Load(nameof(NameOfMyNamespace))dobrze działającego.
Harvey
28
using System.Reflection;
using System.Collections.Generic;//...staticList<string>GetClasses(string nameSpace){Assembly asm =Assembly.GetExecutingAssembly();List<string> namespacelist =newList<string>();List<string> classlist =newList<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;//...staticIEnumerable<string>GetClasses(string nameSpace){Assembly asm =Assembly.GetExecutingAssembly();return asm.GetTypes().Where(type => type.Namespace== nameSpace).Select(type => type.Name);}
Nie próbuję być wredny, ale istnieje całkowicie niepotrzebna lista i iteracja przez wszystkie znalezione elementy w tym kodzie; zmienna „classlist” i przeglądanie poprzez „listę nazw” nie zapewniają żadnej funkcji innej niż zwracanie „listy nazw”
TheXenocide 19.09.08
10
@ TheXenocide cel próbki kodu nie zawsze ma na celu pokazać „najlepszy” sposób pisania kodu, ale jasno przekazać, jak coś się robi.
Ryan Farley,
4
Po prostu wskazywałem na to ze względu na edukację; naszym obowiązkiem jest sprawienie, aby ludzie materialni uczyli się z najlepszego możliwego przykładu, zamiast ryzykować zły przykład, który negatywnie wpływa na zrozumienie. Nie twierdzę, że w szczególności jest to szkodliwe, ale nie zgadzam się z sentymentem
TheXenocide
4
Głosuję nad odpowiedzią, jeżeli nie jest to pomocne w zadanym pytaniu. Wskazówka, którą widzisz po najechaniu kursorem na przycisk głosowania w górę / w dół, mówi „To było pomocne”. Dla mnie decyzja o głosowaniu w górę / w dół zależy od tego, czy była pomocna w udzieleniu odpowiedzi na zadane pytanie.
Ryan Farley
3
Używanie dwóch list i dwóch iteracji pomogło mi tylko spowolnić, próbując dowiedzieć się, dlaczego użyłeś dwóch list, a nie tylko od razu classlistpo pierwszej iteracji nad asm.GetTypes()wynikiem.
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 assembliesAppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve+=newResolveEventHandler(CurrentDomain_ReflectionOnlyAssemblyResolve);Assembly a =System.Reflection.Assembly.ReflectionOnlyLoadFrom(filename);
a.GetTypes();// process types here// method later in the class:staticAssemblyCurrentDomain_ReflectionOnlyAssemblyResolve(object sender,ResolveEventArgs args){returnSystem.Reflection.Assembly.ReflectionOnlyLoad(args.Name);}
To powinno pomóc w ładowaniu typów zdefiniowanych w innych złożeniach.
Na pewno wygląda na pomocny, mniej pomocny i mniej mylący niż kod Ryana Farleya, nawet bez zastanowienia.
ProfK
Przez pewien czas też mnie zdezorientowałeś. Nadal mogę tylko zgadywać, że te elementy Assembly areprezentują normalne przetwarzanie, które może spowodować uruchomienie tego zdarzenia. Nie widzę sensu aw pomaganiu w LoaderExceptionbłędach. Czy mam rację?
ProfK
9
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().
+1 za poprawną odpowiedź. AppDomain.CurrentDomain.GetAssembliesmoże być pomocny.
nawfal
... a następnie przeglądaj je, odfiltrowując te, które nie pasują do przestrzeni nazw.
TJ Crowder
OP specjalnie poprosił o „klasy w przestrzeni nazw”, podczas gdy to powoduje, że „piszesz w asemblerze” - więc ta odpowiedź jest niepełna. Prawidłowa odpowiedź to prawdopodobnie ta , która wylicza tylko klasy ze wszystkich zestawów.
mindplay.dk
6
Podobnie jak odpowiedź @aku, ale przy użyciu metod rozszerzenia:
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{classProgram{staticvoidMain(string[] args ){Console.WriteLine(" START ");// what is in the assemblyAssembly 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 #endregionConsole.ReadLine();Console.WriteLine(" HIT A KEY TO EXIT ");Console.WriteLine(" END ");}}//eof ProgramclassClassOne{}//eof class classClassTwo{}//eof class[System.AttributeUsage(System.AttributeTargets.Class|System.AttributeTargets.Struct,AllowMultiple=true)]publicclassAttributeClass:System.Attribute{publicstringMustHaveDescription{get;set;}publicstringMusHaveVersion{get;set;}publicAttributeClass(string mustHaveDescription,string mustHaveVersion ){MustHaveDescription= mustHaveDescription;MusHaveVersion= mustHaveVersion;}}//eof class }//eof namespace
Jaka jest AttributeClassnazwa MustHaveAttributes? Nie widzę nic związanego z testowaniem, czy klasa ma atrybuty, czy nie. Jest to bardziej mylące niż pomocne.
ProfK
1
Całkiem proste
Type[] types =Assembly.Load(newAssemblyName("mynamespace.folder")).GetTypes();foreach(var item in types){}
I po prostu nie odpowiada na pytanie. Wszystko to polega na uzyskaniu listy wszystkich typów w jednym zestawie, niezależnie od konkretnej przestrzeni nazw.
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.
źródło
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ź:Powinno to działać, chyba że chcesz klas innych domen. Aby uzyskać listę wszystkich domen, kliknij ten link.
źródło
&& 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 iGetAssemblies().SelectMany(t => t.GetTypes())
da wszystkie typy (klasy, struktury itp.) ze wszystkich zespołów.Assembly.Load(nameof(NameOfMyNamespace))
dobrze działającego.NB: Powyższy kod ilustruje, co się dzieje. Gdybyś go wdrożył, możesz użyć uproszczonej wersji:
źródło
classlist
po pierwszej iteracji nadasm.GetTypes()
wynikiem.Dla konkretnego zestawu, NameSpace i ClassName:
Uwaga: Projekt musi odwoływać się do zestawu
źródło
Oto poprawka błędów LoaderException, które prawdopodobnie znajdziesz, jeśli jeden z typów podklasuje typ w innym zestawie:
To powinno pomóc w ładowaniu typów zdefiniowanych w innych złożeniach.
Mam nadzieję, że to pomaga!
źródło
Assembly a
reprezentują normalne przetwarzanie, które może spowodować uruchomienie tego zdarzenia. Nie widzę sensua
w pomaganiu wLoaderException
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()
.źródło
AppDomain.CurrentDomain.GetAssemblies
może być pomocny.Podobnie jak odpowiedź @aku, ale przy użyciu metod rozszerzenia:
źródło
Uzyskaj wszystkie klasy według części nazwy Przestrzeni nazw w jednym wierszu:
źródło
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 ()
źródło
źródło
AttributeClass
nazwaMustHaveAttributes
? Nie widzę nic związanego z testowaniem, czy klasa ma atrybuty, czy nie. Jest to bardziej mylące niż pomocne.Całkiem proste
źródło