2012-02-07 13 views
6

Estoy tratando de usar el evento AppDomain.AssemblyResolve para manejar excepciones mientras resuelvo los ensamblados de algunos dll cargados en el tiempo de ejecución (SerializationException for dynamically loaded Type).Trabajando con el evento AppDomain.AssemblyResolve

Cuando se dispara el evento, me carga todos los archivos DLL en mi directorio y crear una matriz Assembly, entonces yo utilizo este método para obtener la Assembly que contiene el tipo especifico:

public static Assembly GetAssemblyContainingType(String completeTypeName, Assembly[] assemblies) 
    { 
     Assembly assembly = null; 

     foreach (Assembly currentassembly in assemblies) 
     { 
      Type t = currentassembly.GetType(completeTypeName, false, true); 
      if (t != null) 
      { 
       assembly = currentassembly; 
       break; 
      } 
     } 

     return assembly; 
    } 

El problema es que esta el código solo funciona con AssemblyQualifiedName, y el ResolveEventArgs.Name proporcionado por el evento no es tan útil.

¿Me puede sugerir alguna solución?

¿Hay alguna manera de transmitir otros argumentos al evento cuando se dispara?

Respuesta

12

Se puede definir un diccionario de las asambleas de su directorio, así:

private readonly IDictionary<string,Assembly> additional = 
    new Dictionary<string,Assembly>(); 

carga este diccionario con las asambleas de su directorio conocida, como esto:

foreach (var assemblyName ... corresponding to DLL names in your directory...) { 
    var assembly = Assembly.Load(assemblyName); 
    additional.Add(assembly.FullName, assembly); 
} 

proporcionar una implementación para el gancho ...

private Assembly ResolveAssembly(Object sender, ResolveEventArgs e) { 
    Assembly res; 
    additional.TryGetValue(e.Name, out res); 
    return res; 
} 

... y conéctelo al evento:

AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ResolveAssembly; 
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; 

Esto debería hacer el truco.

+5

¿La precarga de los ensamblajes evita la necesidad de un manejador de eventos AssemblyResolve? –

+2

@mikez Por lo que yo sé, simplemente cargar un ensamblaje usando 'Assembly.Load (assemblyName)' no lo pone automáticamente a disposición del código de resolución de conjunto de su dominio de aplicación (a menos que ese código pueda acceder al ensamblado usando la resolución predeterminada proceso). Este código se elimina de un sistema en funcionamiento (eliminé el código de manejo de errores, por ejemplo, alrededor de la llamada 'additional.TryGetValue (e.Name, out res)' para simplificar un poco las cosas). Cuando elimino el gancho 'ResolveAssembly', mi sistema de trabajo deja de funcionar :) – dasblinkenlight

+2

Cuando está compilando el diccionario, use AssemblyName.GetAssemblyName () en lugar de Assmebly.Load para obtener el nombre del ensamblado en asignaciones de nombre de archivo y evitar incondicionalmente cargando todos los ensambles. –

0

Si conoce la lista de ensamblajes que pueden contener tipo que planea deserializar, podría ser mejor simplemente precargar todos los ensamblajes antes de realizar la serialización.

Cuando se desencadena el evento AssemblyResolve no tiene información sobre qué tipo causó la carga, sino solo el nombre del ensamblado. No está claro por qué buscaría ensamblado por algún tipo particular en este caso.

Tenga en cuenta que si 2 ensamblajes tienen la misma identidad (es decir, nombre de archivo en mayúsculas) y uno ya está cargado, el evento no se activará incluso si no se encuentra el tipo en ensamblado ya cargado.

Enlace al artículo con fines históricos: Resolving Assembly Loads.

+0

Como también puede leer en mi pregunta anterior http://stackoverflow.com/q/9158353/1061499 Estoy trabajando en una aplicación que utiliza un enfoque de complemento para cargar varias aplicaciones de una interfaz en tiempo de ejecución.Cuando la aplicación se cierra, necesito serializar estos objetos, luego, cuando la aplicación se reinicia, estos objetos deben ser deserializados. El problema es que los tipos de objeto se cargan en tiempo de ejecución, por lo que su tipo no se resuelve ... – davioooh

Cuestiones relacionadas