Como você obtém todas as classes em um espaço para nome através da reflexão em C #?
Como você obtém todas as classes em um espaço para nome através da reflexão em C #?
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.
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));
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:
AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(t => t.GetTypes())
.Where(t => t.IsClass && t.Namespace == @namespace)
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.
&& 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 e GetAssemblies().SelectMany(t => t.GetTypes())
todos os tipos (classes, estruturas etc.) de todos os conjuntos.
Assembly.Load(nameof(NameOfMyNamespace))
funcionou bem.
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;
}
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;
//...
static IEnumerable<string> GetClasses(string nameSpace)
{
Assembly asm = Assembly.GetExecutingAssembly();
return asm.GetTypes()
.Where(type => type.Namespace == nameSpace)
.Select(type => type.Name);
}
classlist
primeira iteração sobre o asm.GetTypes()
resultado.
Para um assembly específico, 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: O projeto deve fazer referência à montagem
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 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);
}
Isso deve ajudar no carregamento dos tipos definidos em outras montagens.
Espero que ajude!
Assembly a
material representa o processamento normal que pode causar o disparo desse evento. Não vejo utilidade a
em ajudar com LoaderException
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.
AppDomain.CurrentDomain.GetAssemblies
pode ser útil.
Assim como a resposta @aku, mas usando métodos de extensão:
string @namespace = "...";
var types = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.IsClass && t.Namespace == @namespace)
.ToList();
types.ForEach(t => Console.WriteLine(t.Name));
Obtenha todas as classes por parte do nome do espaço para nome em apenas uma linha:
var allClasses = Assembly.GetExecutingAssembly().GetTypes().Where(a => a.IsClass && a.Namespace != null && a.Namespace.Contains(@"..your namespace...")).ToList();
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
{
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
o 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.
Bem simples
Type[] types = Assembly.Load(new AssemblyName("mynamespace.folder")).GetTypes();
foreach (var item in types)
{
}