2011-02-07 23 views
8

Estoy usando el Activator para crear una nueva clase basada en el nombre abreviado de un ensamblaje (p.ej. 'CustomModule'). Lanza un FileNotFoundException, porque el ensamblaje no está allí. ¿Hay alguna manera de verificar si un determinado nombre de ensamblado está presente?¿Cómo verificar si existe un cierto ensamblaje?

estoy usando el siguiente código:

System.Runtime.Remoting.ObjectHandle obj = 
    System.Activator.CreateInstance(assemblyName, className); 

El principal objetivo es poner a prueba en lugar de la presencia de la asamblea que esperar a que la excepción que se produzca.

+0

¿Quiere decir cargado en el dominio de la aplicación actual? ¿Qué es 'assemblyName'? ¿Un nombre de ensamblado totalmente calificado o una ruta de archivo física? –

+0

@MrDisaapointment lo único que sé es que tengo un "CustomModule" en mi base de datos. Si un CustomModule.dll está presente en mi bin o GAC (!?) De lo que producirá la clase especificada por classname. –

+0

Ver mi última actualización, espero que esto sea suficiente para continuar. –

Respuesta

8

Si nota mi comentario a su pregunta, será evidente que no estoy seguro exactamente cómo quiere o necesita hacer esto, pero hasta que tengamos una descripción más elaborada, solo puedo ofrecer esto con la esperanza de que le quede bien a su situación (la clave está en "busca de los montajes):

var className = "System.Boolean"; 
var assemblyName = "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; 
var assemblies = AppDomain.CurrentDomain.GetAssemblies(); 
var assembly = (from a in assemblies 
       where a.FullName == assemblyName 
       select a).SingleOrDefault(); 
if (assembly != null) 
{ 
    System.Runtime.Remoting.ObjectHandle obj = 
     System.Activator.CreateInstance(assemblyName, className);    
} 

.NET 2.0 Compatible Código

Assembly assembly = null; 
var className = "System.Boolean"; 
var assemblyName = "mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; 

foreach (var a in AppDomain.CurrentDomain.GetAssemblies()) 
{ 
    if (a.FullName == assemblyName) 
    { 
     assembly = a; 
     break; 
    } 
} 

if (assembly != null) 
{ 
    System.Runtime.Remoting.ObjectHandle obj = 
     System.Activator.CreateInstance(assemblyName, className); 
} 

Si desea determinar si es o no el archivo existe antes de intentar lo anuncio que (una buena práctica), entonces, dado que tiene su nombre y saber la ubicación deseada, basta con tratar de encontrar el archivo cuando se está resolviendo la asamblea:

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 

var className = "StackOverflowLib.Class1"; 
var assemblyName = "StackOverflowLib.dll"; 
var currentAssemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 
var obj = Activator.CreateInstance(Path.Combine(currentAssemblyPath, assemblyName), className); 

static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
{ 
    var currentAssemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 
    if (File.Exists(Path.Combine(currentAssemblyPath, args.Name))) 
    { 
     return Assembly.LoadFile(Path.Combine(currentAssemblyPath, args.Name)); 
    } 
    return null; 
} 
+0

@MrDisappointment, gracias por el código Fallé al especificar que estoy trabajando en .Net 2.0 –

+1

¿Esto no solo devuelve ensamblajes que ya están cargados en AppDomain? – mmix

+0

@mmix tiene un punto válido. Es posible que tenga un dll presente en el directorio bin que no se haya cargado. –

1

El ensamblaje faltante definitivamente constituye una excepción, intente/capture FileNotFoundException y maneje la situación de acuerdo con su lógica.

+0

100% cierto! Pero me gustaría probarlo, en lugar de esperar a que ocurra la excepción. –

+0

En la parte superior de mi cabeza, no creo que pueda manejar esto fácilmente, ya que tiene que emular un algoritmo de exploración completo. También es propenso a errores (debería decir que el dominio de la aplicación instala su propio proceso de prueba). Para una primera ojeada de parada, si todavía desea esto, consulte este enlace: [Cómo el tiempo de ejecución localiza los ensamblajes]: http://msdn.microsoft.com/en-us/library/yx7xezcf.aspx – mmix

2

creo que no es mejor tratar de evitar La excepción. La razón es que si usted tiene un código como

if (DoesAssemblyExist(asmName)) { 
    object = Activator.CreateInstance(typeName); 
} 
else { 
    MessageBox.Show("Assembly does not exist"); 
} 

siempre hay un riesgo en un sistema operativo multitarea preventiva que podría añadirse el montaje/eliminado entre el cheque y la creación real. Sí, me doy cuenta de que este riesgo es mínimo, pero sigo pensando que la variante de excepción se ve mejor porque es atómica.

-1

espero que ayudará a alguien en el futuro:

En cada .dll externo que está utilizando, crear su propia clave uniqe, así:

cadena de clave = "fjrj3288skckfktk4owoxkvkfk4o29dic";

Y luego, cuando se carga el formulario, por cada .dll externa única que tienes, sólo tiene que comprobar si existe la clave es así:

Si (clave isMyLib.Variables.key ==) // continuar

else // .dll no existe o roto.

Cuestiones relacionadas