2009-05-12 14 views
16

Aquí está mi problema:C# Reflection: ¿Obtiene * todos * ensambles activos en una solución?

Tengo 2 proyectos, uno 'común' que actúa como una biblioteca con todo tipo de código de soporte, y el programa real que utiliza dicho proyecto en muchas de sus llamadas. Llamaremos a estos proyectos "Común" y "Programa". Ambos están en la misma solución.

Dentro de "Común", tengo una clase para tareas de reflexión de commo, como crear una instancia. Si llamo a GetExecutingAssembly, obtiene todos los tipos "comunes", sin embargo, cuando uso GetEntryAssembly obtengo los tipos de "Programa".

Aunque sin duda podría editar el código para trabajar con 2 conjuntos de asm, me temo que hay una situación en la que hay más de 2 proyectos en la solución, digamos 5 (no sé por qué, pero permite solo ve por ahora), y me temo que al llamar a GetExecutingAssembly y GetEntryAssembly no obtendrás todos los tipos en todo el programa.

¿Hay algo más que pueda hacer para obtener todos los tipos en una solución ?

Respuesta

49
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); 

Esto obtendrá todos los conjuntos cargados en el Dominio de aplicación actual.

Como se señaló en los comentarios, es posible generar varios AppDomains, en cuyo caso cada uno puede tener sus propios ensamblajes. La ventaja inmediata de hacerlo es que puede descargar Assemblies descargando el AppDomain que lo contiene.

+3

puede o no puede trabajar sujeta a 1) si la aplicación genera múltiples dominios de aplicación 2) Si todos los conjuntos de ref se han cargado antes de este punto – Gishu

+1

Perfecto, gracias! – cyberconte

+0

@Gishu: "si todos los ensamblados de referencia se han cargado antes de este punto" No estoy seguro de qué quiere decir con eso. ¿Puedes elaborar? – bsneeze

7

¿Qué tal GetReferencedAssemblies para trabajar con las entradas de metadatos de AssemblyRef? La 'solución' no es algo que el CLR sepa o le interese ... se trata de Asambleas.

private static List<Assembly> GetListOfEntryAssemblyWithReferences() 
{ 
    List<Assembly> listOfAssemblies = new List<Assembly>(); 
    var mainAsm = Assembly.GetEntryAssembly(); 
    listOfAssemblies.Add(mainAsm); 

    foreach (var refAsmName in mainAsm.GetReferencedAssemblies()) 
    { 
    listOfAssemblies.Add(Assembly.Load(refAsmName)); 
    } 
    return listOfAssemblies; 
} 

Advertencias:
1. Todavía es necesario para filtrar Sistema de conjuntos de núcleo * 2. Esto sólo sirve un nivel de profundidad en la cadena de ref .. pero se puede hacer de forma recursiva - con más código..

5

También: Algunos ensamblados no se cargan inmediatamente, por lo que también debe colocar un Controlador de eventos en el evento de carga de ensamblaje del Dominio de aplicaciones.

AppDomain.CurrentDomain.AssemblyLoad += .... 
29

Ésta es una vieja pregunta realmente, pero para futura referencia aquí es una aplicación completa:

public static IEnumerable<Assembly> GetAssemblies() 
    { 
     var list = new List<string>(); 
     var stack = new Stack<Assembly>(); 

     stack.Push(Assembly.GetEntryAssembly()); 

     do 
     { 
      var asm = stack.Pop(); 

      yield return asm; 

      foreach (var reference in asm.GetReferencedAssemblies()) 
       if (!list.Contains(reference.FullName)) 
       { 
        stack.Push(Assembly.Load(reference)); 
        list.Add(reference.FullName); 
       } 

     } 
     while (stack.Count > 0); 

    } 
+0

Agradable, gracias por compartir, justo lo que necesitaba. – Dav

+0

@Dav de nada! –

+0

Intente usar hashset insteas de una lista. – AgentFire

Cuestiones relacionadas