você pode editar sua pergunta ... a questão do subtexto é mais comunicativa do que o 'Namespace in C #' #
392
Você pode procurar aqui . Existem 2 amostras diferentes.
Fatih GÜRDAL 15/11
Respostas:
317
O código a seguir imprime os nomes das classes especificadas namespacedefinidas na montagem atual.
Como outros caras apontaram, um espaço para nome pode ser espalhado entre diferentes módulos; portanto, é necessário obter uma lista dos assemblies primeiro.
Como o FlySwat diz, você pode ter o mesmo espaço para nome em vários assemblies (por exemplo System.Collections.Generic). Você precisará carregar todos esses conjuntos se eles ainda não estiverem carregados. Então, para uma resposta completa:
funciona bem - um pequeno lembrete: Eu tentei remover " && t.Namespace == @namespace" - que ofcause me deu tudo .net montagens :-)
Netsi1964
@ Netsi1964, se você remover, && t.Namespace == @namespaceobtém todas as classes de todos os assemblies , incluindo os .net. GetAssembliesfornecerá todos os conjuntos e GetAssemblies().SelectMany(t => t.GetTypes())todos os tipos (classes, estruturas etc.) de todos os conjuntos.
Nawfal
Atualizei para o DotNet Core 2.2 (da 2.1) e esse código parou de funcionar para meu assembly específico. O assembly que eu queria não foi referenciado em nenhum lugar do código, portanto não foi carregado! Em 2.1 foi carregado, mas 2.2 parece ter carregamento lento?
Harvey
@ Harvey O .NET Core tem domínio de aplicativo para começar?
Nawfal 26/08/19
@nawfal Yeah. Este código funcionou anteriormente no 2.1. Descobri que forço o carregamento de uma montagem usando Assembly.Load(nameof(NameOfMyNamespace))funcionou bem.
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;}
Nota: O código acima ilustra o que está acontecendo. Se você implementá-lo, uma versão simplificada pode ser usada:
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);}
Não estou tentando ser mesquinho, mas há uma lista e iteração totalmente desnecessárias em todos os itens encontrados neste código; a variável "classlist" e foreach através de "namespacelist" fornecer nenhuma funcionalidade diferente de retornar "namespacelist"
TheXenocide
10
@TheXenocide: o objetivo de uma amostra de código nem sempre tem como objetivo mostrar a "melhor" maneira de escrever código, mas transmitir claramente como algo é feito.
Ryan Farley
4
Eu estava apenas apontando isso por uma questão de educação; é nossa responsabilidade fazer com que as pessoas materiais aprendam com o melhor exemplo possível, em vez de arriscar um mau exemplo que influencia negativamente a compreensão. Não estou dizendo que este em particular é prejudicial, mas eu discordo com o sentimento
TheXenocide
4
Eu voto uma resposta para baixo, se não for útil para a pergunta que foi feita. A dica que você vê ao passar o mouse sobre o botão de votação para cima / para baixo diz "Isso foi útil". A decisão de votar para cima / para baixo em uma resposta, para mim, é se foi útil ou não para responder à pergunta.
22480 Ryan Farley
3
A única coisa que você usou duas listas e duas iterações ajudou foi me atrasar tentando descobrir por que você usou duas listas e não apenas adicionou diretamente à classlistprimeira iteração sobre o asm.GetTypes()resultado.
ProfK 26/10
20
Para um assembly específico, NameSpace e ClassName:
Aqui está uma correção para os erros do LoaderException que você provavelmente descobrirá se um dos tipos sub-submete um tipo em outro assembly:
// 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);}
Isso deve ajudar no carregamento dos tipos definidos em outras montagens.
Certamente parece útil, e menos útil e menos confuso do que o código de Ryan Farley, mesmo sem pensar nisso.
ProfK 26/10/14
Você também me deixou confuso por um tempo. Ainda posso adivinhar que o Assembly amaterial representa o processamento normal que pode causar o disparo desse evento. Não vejo utilidade aem ajudar com LoaderExceptionerros. Estou certo?
ProfK 26/10/14
9
Você não poderá obter todos os tipos em um espaço para nome, porque um espaço para nome pode conectar vários assemblies, mas você pode obter todas as classes em um assembly e verificar se elas pertencem a esse espaço para nome.
Assembly.GetTypes()funciona na montagem local ou você pode carregar uma montagem primeiro e depois ligá GetTypes()-la.
+1 para a resposta correta. AppDomain.CurrentDomain.GetAssembliespode ser útil.
Nawfal
... e depois percorre-os, filtrando os que não correspondem ao espaço para nome.
TJ Crowder
O OP pediu especificamente "classes em um espaço para nome", enquanto isso faz com que você "digite um assembly" - portanto, essa resposta está incompleta. A resposta correta é provavelmente essa , que enumera apenas classes, de todos os assemblies.
mindplay.dk 14/04
6
Assim como a resposta @aku, mas usando métodos de extensão:
Os espaços para nome são realmente bastante passivos no design do tempo de execução e servem principalmente como ferramentas organizacionais. O nome completo de um tipo no .NET consiste no espaço para nome e na classe / enum / etc. combinado. Se você deseja apenas passar por uma montagem específica, basta percorrer os tipos retornados pela montagem. GetExportedTypes () verificando o valor do tipo Namespace . Se você estivesse tentando passar por todos os assemblies carregados no AppDomain atual, isso envolveria o uso de 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
Qual AttributeClasso nome do nome MustHaveAttributes? Não vejo nada relacionado a testar se uma classe tem atributos ou não. Isso é mais confuso do que útil.
ProfK 26/10/14
1
Bem simples
Type[] types =Assembly.Load(newAssemblyName("mynamespace.folder")).GetTypes();foreach(var item in types){}
E simplesmente não respondendo à pergunta. Tudo o que está fazendo é obter uma lista de todos os tipos em um único assembly, independentemente de qualquer espaço para nome específico.
Respostas:
O código a seguir imprime os nomes das classes especificadas
namespace
definidas na montagem atual.Como outros caras apontaram, um espaço para nome pode ser espalhado entre diferentes módulos; portanto, é necessário obter uma lista dos assemblies primeiro.
fonte
Como o FlySwat diz, você pode ter o mesmo espaço para nome em vários assemblies (por exemplo
System.Collections.Generic
). Você precisará carregar todos esses conjuntos se eles ainda não estiverem carregados. Então, para uma resposta completa:Isso deve funcionar, a menos que você queira classes de outros domínios. Para obter uma lista de todos os domínios, siga este link.
fonte
&& t.Namespace == @namespace
" - que ofcause me deu tudo .net montagens :-)&& t.Namespace == @namespace
obtém todas as classes de todos os assemblies , incluindo os .net.GetAssemblies
fornecerá todos os conjuntos eGetAssemblies().SelectMany(t => t.GetTypes())
todos os tipos (classes, estruturas etc.) de todos os conjuntos.Assembly.Load(nameof(NameOfMyNamespace))
funcionou bem.Nota: O código acima ilustra o que está acontecendo. Se você implementá-lo, uma versão simplificada pode ser usada:
fonte
classlist
primeira iteração sobre oasm.GetTypes()
resultado.Para um assembly específico, NameSpace e ClassName:
Nota: O projeto deve fazer referência à montagem
fonte
Aqui está uma correção para os erros do LoaderException que você provavelmente descobrirá se um dos tipos sub-submete um tipo em outro assembly:
Isso deve ajudar no carregamento dos tipos definidos em outras montagens.
Espero que ajude!
fonte
Assembly a
material representa o processamento normal que pode causar o disparo desse evento. Não vejo utilidadea
em ajudar comLoaderException
erros. Estou certo?Você não poderá obter todos os tipos em um espaço para nome, porque um espaço para nome pode conectar vários assemblies, mas você pode obter todas as classes em um assembly e verificar se elas pertencem a esse espaço para nome.
Assembly.GetTypes()
funciona na montagem local ou você pode carregar uma montagem primeiro e depois ligáGetTypes()
-la.fonte
AppDomain.CurrentDomain.GetAssemblies
pode ser útil.Assim como a resposta @aku, mas usando métodos de extensão:
fonte
Obtenha todas as classes por parte do nome do espaço para nome em apenas uma linha:
fonte
Os espaços para nome são realmente bastante passivos no design do tempo de execução e servem principalmente como ferramentas organizacionais. O nome completo de um tipo no .NET consiste no espaço para nome e na classe / enum / etc. combinado. Se você deseja apenas passar por uma montagem específica, basta percorrer os tipos retornados pela montagem. GetExportedTypes () verificando o valor do tipo Namespace . Se você estivesse tentando passar por todos os assemblies carregados no AppDomain atual, isso envolveria o uso de AppDomain.CurrentDomain. GetAssemblies ()
fonte
fonte
AttributeClass
o nome do nomeMustHaveAttributes
? Não vejo nada relacionado a testar se uma classe tem atributos ou não. Isso é mais confuso do que útil.Bem simples
fonte