2011-01-14 20 views
47

Necesito buscar tipos específicos en todos los ensamblajes en un sitio web o aplicación de Windows, ¿hay alguna manera fácil de hacerlo? Me gusta cómo la fábrica de controladores para ASP.NET MVC se ve en todos los ensamblajes para los controladores.Buscar tipos en todos los ensamblajes

Gracias.

Respuesta

79

hay dos pasos de conseguirlo:

  • El AppDomain.CurrentDomain.GetAssemblies() le da todos los ensamblados cargados en el dominio de aplicación actual.
  • La clase Assembly proporciona un método GetTypes() para recuperar todos los tipos dentro de ese ensamblaje en particular.

De ahí su código podría tener este aspecto:

foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) 
{ 
    foreach (Type t in a.GetTypes()) 
    { 
     // ... do something with 't' ... 
    } 
} 

Para buscar tipos específicos (por ejemplo, la implementación de una interfaz dada, heredando de un ancestro común o lo que sea) que tendrá que filtrar la salida resultados. En caso de que necesites hacer eso en varios lugares de tu aplicación, es una buena idea construir una clase de ayuda con diferentes opciones. Por ejemplo, comúnmente he aplicado filtros de prefijo de espacio de nombre, filtros de implementación de interfaz y filtros de herencia.

Para obtener documentación detallada eche un vistazo a MSDN here y here.

+0

Por supuesto, si vas a hacer algunos filtros en esos tipos y ensamblajes, usarás LINQ, ¿verdad? ;) –

+6

@Niall Connaughton Esa es una cuestión de preferencia personal. –

+2

He encontrado situaciones en las que hacer esto provoca una excepción, resultó ser porque mi aplicación estaba generando ensamblajes dinámicos, solo tengo que tener en cuenta. Puede identificar los conjuntos dinámicos y omitirlos así http://stackoverflow.com/questions/1423733/how-to-tell-if-a-net-assembly-is-dynamic - si causa un problema –

26

fácil usando LINQ: solución

IEnumerable<Type> types = 
      from a in AppDomain.CurrentDomain.GetAssemblies() 
      from t in a.GetTypes() 
      select t; 

foreach(Type t in types) 
{ 
    ... 
} 
19

LINQ con comprobación para ver si el conjunto es dinámico:

/// <summary> 
/// Looks in all loaded assemblies for the given type. 
/// </summary> 
/// <param name="fullName"> 
/// The full name of the type. 
/// </param> 
/// <returns> 
/// The <see cref="Type"/> found; null if not found. 
/// </returns> 
private static Type FindType(string fullName) 
{ 
    return 
     AppDomain.CurrentDomain.GetAssemblies() 
      .Where(a => !a.IsDynamic) 
      .SelectMany(a => a.GetTypes()) 
      .FirstOrDefault(t => t.FullName.Equals(fullName)); 
} 
4

Lo más común es que sólo está interesado en las asambleas que son visibles desde el exterior . Por lo tanto, debe llamar al GetExportedTypes() Pero además de eso, puede lanzarse una ReflectionTypeLoadException. El siguiente código se ocupa de estas situaciones.

public static IEnumerable<Type> FindTypes(Func<Type, bool> predicate) 
{ 
    if (predicate == null) 
     throw new ArgumentNullException(nameof(predicate)); 

    foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) 
    { 
     if (!assembly.IsDynamic) 
     { 
      Type[] exportedTypes = null; 
      try 
      { 
       exportedTypes = assembly.GetExportedTypes(); 
      } 
      catch (ReflectionTypeLoadException e) 
      { 
       exportedTypes = e.Types; 
      } 

      if (exportedTypes != null) 
      { 
       foreach (var type in exportedTypes) 
       { 
        if (predicate(type)) 
         yield return type; 
       } 
      } 
     } 
    } 
} 
Cuestiones relacionadas