¿Cómo se obtienen todas las clases en un espacio de nombres a través de la reflexión en C #?
¿Cómo se obtienen todas las clases en un espacio de nombres a través de la reflexión en C #?
Respuestas:
El siguiente código imprime los nombres de las clases especificadas namespace
en el ensamblaje actual.
Como otros muchachos señalaron, un espacio de nombres puede estar disperso entre diferentes módulos, por lo que primero debe obtener una lista de ensamblajes.
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 dice FlySwat, puede tener el mismo espacio de nombres que abarca varios ensamblajes (por ejemplo, por ejemplo System.Collections.Generic
). Tendrá que cargar todos esos ensamblajes si aún no están cargados. Entonces, para una respuesta completa:
AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(t => t.GetTypes())
.Where(t => t.IsClass && t.Namespace == @namespace)
Esto debería funcionar a menos que desee clases de otros dominios. Para obtener una lista de todos los dominios, siga este enlace.
&& t.Namespace == @namespace
", lo que me dio todos los ensamblados .net :-)
&& t.Namespace == @namespace
, obtiene todas las clases de todos los ensamblados , incluidos .net. GetAssemblies
le dará todos los ensamblajes y GetAssemblies().SelectMany(t => t.GetTypes())
todos los tipos (clases, estructuras, etc.) de todos los ensamblajes.
Assembly.Load(nameof(NameOfMyNamespace))
trabajado bien.
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: el código anterior ilustra lo que está sucediendo. Si lo implementara, se puede utilizar una versión simplificada:
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
la primera iteración sobre el asm.GetTypes()
resultado.
Para un ensamblado específico, NameSpace y 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: El proyecto debe hacer referencia al ensamblaje.
Aquí hay una solución para los errores de LoaderException que es probable que encuentre si uno de los tipos subclasifica un tipo en otro ensamblado:
// 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);
}
Eso debería ayudar con los tipos de carga definidos en otros ensamblajes.
¡Espero que ayude!
Assembly a
material representa el procesamiento normal que podría provocar que este evento se active. No veo ninguna utilidad para a
ayudar con los LoaderException
errores. Estoy en lo cierto?
No podrá obtener todos los tipos en un espacio de nombres, porque un espacio de nombres puede unir múltiples ensamblajes, pero puede obtener todas las clases en un ensamblaje y verificar si pertenecen a ese espacio de nombres.
Assembly.GetTypes()
funciona en el ensamblaje local, o puede cargar un ensamblaje primero y luego llamarlo GetTypes()
.
AppDomain.CurrentDomain.GetAssemblies
puede ser útil
Al igual que @aku answer, pero usando métodos de extensión:
string @namespace = "...";
var types = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.IsClass && t.Namespace == @namespace)
.ToList();
types.ForEach(t => Console.WriteLine(t.Name));
Obtenga todas las clases por parte del nombre del espacio de nombres en una sola fila:
var allClasses = Assembly.GetExecutingAssembly().GetTypes().Where(a => a.IsClass && a.Namespace != null && a.Namespace.Contains(@"..your namespace...")).ToList();
Los espacios de nombres son bastante pasivos en el diseño del tiempo de ejecución y sirven principalmente como herramientas organizativas. El nombre completo de un tipo en .NET consiste en el espacio de nombres y Clase / Enum / Etc. conjunto. Si solo desea pasar por un ensamblaje específico, simplemente recorrerá los tipos devueltos por el ensamblaje. GetExportedTypes () comprobando el valor de tipo. Espacio de nombres . Si intentara pasar por todos los ensamblados cargados en el AppDomain actual, implicaría usar 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
el nombre MustHaveAttributes
? No veo nada relacionado con probar si una clase tiene atributos o no. Esto es más confuso que útil.
Bastante sencillo
Type[] types = Assembly.Load(new AssemblyName("mynamespace.folder")).GetTypes();
foreach (var item in types)
{
}