2008-09-17 8 views

Respuesta

18
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; 
} 
+0

Nota: Puede hacerlo siempre que ingrese el conjunto y la NS que debe buscar. Los tipos se pueden definir en ensamblajes múltiples y pertenecen a la misma NS. – Gishu

+0

Eso es cierto Gishu. Supongo que sería mejor pasar el conjunto, así como el espacio de nombres del ensamblado, para eliminar la ambigüedad. –

+1

"namespace" - palabra clave reservada, debe agregar @ prefix para compilar este código – aku

9

Usted no será capaz de obtener todo tipo en un espacio de nombres, debido a que un espacio de nombres puede conectar varias asambleas, pero se puede llegar a todas las clases en una asamblea y comprobar para ver si pertenecen a ese espacio de nombres.

Assembly.GetTypes() trabaja en el ensamblaje local, o puede cargar un ensamblaje primero y luego llamar al GetTypes().

+1

+1 para la respuesta correcta. 'AppDomain.CurrentDomain.GetAssemblies' puede ser útil. – nawfal

+0

... y luego recorrerlos, filtrando los que no coinciden con el espacio de nombres. –

270

El siguiente código imprime los nombres de las clases en namespace especificado en el ensamblaje actual.
Como señalaron otros tipos, 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)); 
3

Los espacios de nombres son realmente bastante pasivos en el diseño del tiempo de ejecución y sirven principalmente como herramientas de organización. El nombre completo de un tipo en .NET consiste en Namespace y Class/Enum/Etc. conjunto. Si solo desea pasar por un ensamblaje específico, simplemente recorrerá los tipos devueltos por el ensamblaje. GetExportedTypes() comprobando el valor del tipo. Namespace. Si estuviera tratando de pasar por todos los ensamblados cargados en el actual AppDomain, implicaría el uso de AppDomain.CurrentDomain. GetAssemblies()

12

Aquí es una solución para los errores LoaderException es muy probable que encontrar si uno de los tipos sublasses un tipo en otro montaje:

// 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 definidas en otros conjuntos.

Espero que ayude!

+0

Claro que se ve útil, y menos útil y menos confuso que el código de Ryan Farley, incluso sin pensarlo. – ProfK

+0

Aunque también me has confundido por un tiempo. Todavía puedo adivinar que el material 'Assembly a' representa el procesamiento normal que podría provocar el desencadenamiento de este evento. No veo uso para 'a' al ayudar con los errores' LoaderException'. ¿Estoy en lo cierto? – ProfK

2
//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 
+0

¿Qué son'AttributeClass' el nombre 'MustHaveAttributes'? No veo nada relacionado con probar si una clase tiene atributos o no. Esto es más confuso que útil. – ProfK

5

Al igual que la respuesta @aku, pero utilizando 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)); 
60

Como dice flyswat, que pueden tener el mismo espacio de nombres que abarca en varios ensamblados (por ejemplo System.Collections.Generic). Deberá cargar todos los 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 this link.

+1

funciona bien - un pequeño recordatorio: traté de eliminar "' && t.Namespace == @ namespace' "- que por causa me dio ** todos los ** .NET assemblies :-) – Netsi1964

+0

@ Netsi1964 si elimina' && t.Namespace == @ namespace' obtienes todas * clases * de * todos los ensamblados *, incluido .net's. 'GetAssemblies' le dará todos los ensamblados, y' GetAssemblies(). SelectMany (t => t.GetTypes()) 'dará todos los tipos (clases, estructuras, etc.) de todos los ensamblajes. – nawfal

2

conseguir todas las clases por parte del nombre de 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(); 
8

Para una Asamblea específica, con un filtro de nombre de la clase:

var asm = Assembly.Load("Some.Assembly.Name"); 
var nameSpace = "Some.Namespace.Name"; 

var classes = asm.GetTypes().Where(p => 
    p.Namespace == nameSpace && 
    p.Name.Contains("ClassNameFilter") 
).ToList(); 

Nota: el proyecto debe hacer referencia al ensamblado

2

Muy sencillo

Type[] types = Assembly.Load(new AssemblyName("mynamespace.folder")).GetTypes(); 
foreach (var item in types) 
{ 
} 
Cuestiones relacionadas