2011-11-04 9 views
7

uso el siguiente código:¿Cómo puedo obtener un tipo de un ensamblaje que se carga desde otra carpeta?

Assembly.LoadFile("the assembly in another folder"); 
var type = Type.GetType("the full name of the type"); 

A pesar de que el conjunto ya se cargó antes de esta línea de código, siempre devuelve un valor nulo en type.

PD: Sí, pasé el nombre completo del ensamblado, incluidos el espacio de nombres, el nombre del tipo, el nombre del ensamblaje, la versión y el token público.

+0

¿Este ensamblaje está relacionado de alguna manera con el lenguaje ensamblador? –

+0

@KirilKirov: No. Es un tipo en .Net. –

+0

@Austin - ah, gracias :) Fui engañado por la etiqueta. –

Respuesta

9

Type.GetType solo busca los tipos en el ensamblado que llama y los tipos en mscorlib.dll a menos que pase el nombre calificado del ensamblado del tipo. See here.

EDITAR

Parece que Type.GetType sólo es capaz de recuperar Type casos de asambleas en el contexto de carga. Los ensamblados cargados usando LoadFile están en no context y los cargados usando LoadFrom están en el contexto Cargar desde; ninguno de estos contextos le permite usar Type.GetType por lo que la resolución fallará. This article muestra que la información Type se puede recuperar para un Assembly cuando el directorio en el que se encuentra se agrega como un privatePath de sondeo, ya que luego terminará en el contexto Cargar pero fallará en otros contextos.

+0

pasé el nombre completo del ensamblado, incluidos el espacio de nombres, el nombre del tipo, el nombre del ensamblado y la versión, token público. – CuiPengFei

+0

@CuiPengFei Solo para eliminar lo obvio, ¿está seguro de que el nombre calificado de ensamblaje coincide exactamente con el valor que distingue entre mayúsculas y minúsculas que obtendría si hacía referencia estáticamente al ensamblado y se llama 'typeof (TypeName) .AssemblyQualifiedName'? –

+0

sí, estoy seguro. – CuiPengFei

1

puede probar esto ....

Assembly.GetAssembly asume que tiene una instancia del tipo y Type.GetType asume que tiene el nombre de tipo completo que incluye nombre de ensamblado.

se puede dar camino que se encuentra el montaje .....

Si sólo tiene el nombre del tipo de base, que tiene que hacer algo más parecido a esto:

public static String GetAssemblyNameContainingType(String typeName) 
{ 
    foreach (Assembly currentassembly in AppDomain.CurrentDomain.GetAssemblies()) 
    { 
     Type t = currentassembly.GetType(typeName, false, true); 
     if (t != null) {return currentassembly.FullName;} 
    } 

    return "not found"; 
} 

Esto también supone que su tipo se declara en la raíz. Debería proporcionar el espacio de nombre o los tipos que lo incluyen en el nombre, o repetir de la misma manera.

+0

Tenga cuidado al cargar ensamblajes porque una vez que los carga en un Dominio de aplicación ya no puede descargarlos. Si tiene que cargar un montón de ensamblajes, piense en crear un AppDomain separado que hará el trabajo de hacer los ensamblados de procesamiento y devolver el resultado, luego de lo cual podrá ser liberado. –

+0

No recomendaría esto. En su lugar, vincule al evento [AppDomain.AssemblyResolve] (http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyload.aspx). De esta manera, solo devuelve el ensamblaje requerido, donde en el código anterior, busca _cada y cada ensamblaje cargado, además de que comienza a cargar los que no se necesitan actualmente_. – Abel

2

La forma más sencilla de hacerlo es simplemente atrapar el valor de retorno de Assembly.LoadFile en una variable y llamar GetType de esta manera:

Assembly assem = Assembly.LoadFile("assemblyLocation"); 
assem.GetType("typeName"); 

Es posible que desee considerar mantener una referencia a este conjunto si desea extraer tipos a menudo, o hacer lo que otros han sugerido y crear un método más genérico que recorra todos los ensamblados cargados.

4

La forma "correcta" (MS recomendada) de hacer esto, cuando debe usar Type.GetType(string) en tipos en ensamblados que no están en el contexto de carga sino en el contexto load-from o no-context, es enlazar a Appdomain.AssemblyResolve evento. El código siguiente es relativamente eficiente:

// this resolver works as long as the assembly is already loaded 
// with LoadFile/LoadFrom or Load(string)/Load(byte[]) 
private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) 
{ 
    var asm = (from a in AppDomain.CurrentDomain.GetAssemblies() 
       where a.GetName().FullName == args.Name 
       select a).FirstOrDefault(); 

    if(asm == null) 
     throw FileNotFoundException(args.Name);  // this becomes inner exc 

    return asm; 
} 

// place this somewhere in the beginning of your app: 
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve; 

Parece ligeramente más eficiente para crear una combinación de los eventos AssemblyLoad/Resolve para mantener un diccionario de los ensamblados cargados (utilizar el ensamblaje de nombre como tecla).

Ensamblaje.LoadFile
Hay un serio inconveniente al usar este método. According to MSDN:

LoadFile no carga archivos en el contexto LoadFrom, y no resuelve dependencias utilizando el camino de carga, como el método LoadFrom hace.

De ser posible, no use LoadFile. El ensamblaje resultante se carga en el contexto sin contexto, que tiene aún más inconvenientes que el contexto load-from. En su lugar, use Assembly.LoadFrom y las dependencias se cargarán automáticamente desde la ruta de carga.

Cuestiones relacionadas