2009-01-21 14 views
5

Estoy teniendo algunos problemas con el siguiente código:Type.IsSubclassOf() no funciona en AppDomains?

private class ClientPluginLoader : MarshalByRefObject 
{ 
    public bool IsPluginAssembly(string filename) 
    { 
     AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(CurrentDomainReflectionOnlyAssemblyResolve); 

     Assembly asm = Assembly.ReflectionOnlyLoadFrom(filename); 

     Type[] types = asm.GetTypes(); 
     foreach (Type type in types) 
     { 
      if (type.IsSubclassOf(typeof(ClientPlugin))) 
      { 
       return true; 
      } 
     } 

     return false; 
    } 
} 

El código se llama a través de un proxy que he creado a través de mi dominio CreateInstanceFromAndUnwrap aplicación personalizada(). Esto significa que IsPluginAssembly() se ejecuta en el contexto de mi dominio de aplicación personalizada.

El problema es que la llamada a IsSubclassOf() siempre devuelve falso, aunque en mi humilde opinión debe ser verdadero. El "tipo" en cuestión realmente hereda de ClientPlugin; no hay dudas al respecto.

ClientPlugin se define en un ensamblaje privado diferente, que estoy resolviendo manualmente, como se evidencia en el fragmento de código anterior.

He puesto un punto de interrupción en la línea if (type.IsSubclassOf(...)) y confirmó esta expresión es falsa:

type.BaseType == typeof(ClientPlugin) 

Por otro lado, esta expresión es verdadera:

type.BaseType.FullName == typeof(ClientPlugin).FullName 

cómo es esto posible ? ¿Que esta pasando?

ACTUALIZACIÓN: Kent Boogaart me indicó la dirección correcta. Busqué en la web un poco más y me encontré con la publicación de blog this. Parece que tendré que resolver mis conflictos Load/LoadFrom/ReflectionOnlyLoadFrom para que esto funcione.

Respuesta

7

Esto se debe a la carga en un contexto diferente. Cómo cargar un ensamblaje (Load/LoadFrom/ReflectionOnlyLoad) determina en qué contexto se carga. Este simple ejemplo también demuestra el problema:

using System; 
using System.Reflection; 

class Foo 
{ 
    public static void Main() 
    { 
     var type = typeof(Foo); 
     var reflectionLoadType = Assembly.ReflectionOnlyLoad("ConsoleApplication1").GetType("Foo"); 
     Console.WriteLine(type == reflectionLoadType); //false 
     Console.WriteLine(type.Equals(reflectionLoadType)); //false 

     Console.WriteLine("DONE"); 
     Console.ReadKey(); 
    } 
} 

Ver here para obtener más información.

2

Tuve un problema similar. También tenía esta arquitectura: una .DLL que contiene la clase base ClientPlugin; varios complementos que hacen referencia a esto .DLL; y una aplicación principal, que también hace referencia a esto .DLL. El problema era que el .DLL con la clase base de ClientPlugin se copió en dos carpetas: la carpeta de complementos y la carpeta de la aplicación principal. Por lo tanto, se cargó dos veces en mi AppDomain (los complementos también lo cargaron de forma indirecta). Y cuando la aplicación principal intentó hacer un tipo de reflejo mágico, falló, porque había dos instancias del tipo ClientPlugin.

Aunque no creo que este sea exactamente su caso, todavía hay una lección que aprender aquí: si un .DLL se carga dos veces, los tipos también se duplicarán. En su caso, sospecho que ya sea AppDomains por separado, o el "ReflectionOnlyLoad", porque el .DLL se carga de alguna manera de manera diferente.

+0

Tuve exactamente este problema, tenía dos copias de la misma DLL en dos carpetas. Al ejecutar el "IsSubclassOf" manualmente, recibí este mensaje de error: El tipo 'ServiceCore.BaseService' existe en 'ServiceCore.dll' y 'ServiceCore.dll' – vpalmu