2008-12-05 30 views
18

Estoy trabajando en un sistema de complemento que carga los archivos .dll contenidos en una carpeta especificada. A continuación, utilizo la reflexión para cargar los ensamblajes, recorrer los tipos que contienen e identificar los que implementan mi interfaz IPlugin.IsAssignableFrom() devuelve falso cuando debería devolver verdadero

estoy comprobando esto con un código similar al siguiente:

foreach(Type t in myTypes) 
{ 
    if(typeof(IPlugin).IsAssignableFrom(t)) 
    { 
     ... 
    } 
} 

Por alguna razón IsAssignableFrom() sigue volviendo falsa cuando debería estar regresando cierto. He intentado reemplazar el t dándole explícitamente un tipo que debería pasar, y funciona bien, pero por alguna razón no funciona con los tipos que se devuelven del ensamblaje cargado. Para hacer las cosas más extrañas, el código funciona bien en la máquina de mi compañero pero no en la mía.

¿Alguien sabe algo que pueda causar este tipo de comportamiento?

Gracias

Respuesta

27

Esto suele ocurrir cuando hay una falta de coincidencia entre el ensamblaje que contiene el tipo IPlugin al que hace referencia el ensamblaje actual y el ensamblado al que hace referencia el ensamblaje que contiene los tipos que está iterando . sobre

sugiero que imprima:

typeof (IPlugin).Module.FullyQualifiedName 

y

foreach (var type in t.GetInterfaces()) 
{  
    Console.WriteLine (type.Module.FullyQualifiedName) 
} 

Para ver dónde está la falta de coincidencia.

+0

En mi caso, la comparación de tipo falla solo en el caso de una interfaz y funciona bien para todas las demás interfaces definidas en el mismo conjunto. ¿Por qué sucedería eso? La interfaz que contiene el ensamblaje se copia en la carpeta "bin \ debug" de la aplicación utilizando el evento post-build del proyecto. Por lo tanto, creo que el ensamblado al que se hace referencia en mi proyecto de inicio (utilizando referencia directa del proyecto) es el mismo que el que se copió en la carpeta "bin \ debug" de la aplicación. No es ese el caso? – Learner

+0

Esto fue todo para mí. Mi módulo rechazaba v2.0.0.0 del ensamblado que contenía el tipo que estaba comprobando, mientras que el tipo que implementaba implementaba un tipo con el mismo nombre de la v2.1.0.0 de ese ensamblaje. –

+1

Me parece que esto falla si los ensamblajes se cargan en un contexto de solo reflejo. Aunque ambos tipos tienen el mismo * AssemblyQualifiedName *. –

0

trabajo en Java, que tiene el mismo método de API y yo no puedo dejar de pensar que asimilo que al leer el código (por alguna razón); por lo tanto, siempre lo leo en reversa porque, en su caso, "t es asignable a IPlugin). Entonces si C# tiene" es "como sugiere Jonathon, siempre lo usaría, cuando reflejar en Java" instanceof "no funciona para Objetos de clase, solo instancias del objeto

-2

El nombre del método Type.IsAssignableFrom es vago y confuso cuando se lo aplica a probar la herencia o detectar implementaciones de interfaz. La siguiente contenedor para estos fines tendría mucho más sentido:

public static bool CanBeTreatedAsType(this Type CurrentType, Type TypeToCompareWith) 
    { 
     // Always return false if either Type is null 
     if (CurrentType == null || TypeToCompareWith == null) 
      return false; 

     // Return the result of the assignability test 
     return TypeToCompareWith.IsAssignableFrom(CurrentType); 
    } 

Entonces, uno puede tener un código de aplicación más comprensible, tales como:

bool CanBeTreatedAs = typeof(SimpleChildClass).CanBeTreatedAsType(typeof(SimpleClass)); 
    CanBeTreatedAs = typeof(SimpleClass).CanBeTreatedAsType(typeof(IDisposable)); 

La ventaja de este método en lugar del 'es' la palabra clave es que se puede usar en tiempo de ejecución para probar tipos arbitrarios y desconocidos, mientras que la palabra clave 'is' (y un parámetro de tipo genérico) requiere conocimiento en tiempo de compilación de tipos específicos.

0

A veces es un problema con el ensamblaje dinámico que hace referencia a otro ensamblaje.

Una cosa simple para hacerlo es deshabilitar la copia local en el ensamblado (en el estudio visual, haga clic derecho en la referencia y establezca copy local en false). Esto debería facilitar el acceso al directorio donde vive el ensamblado.

También puede implementar una resolución de ensamblaje en caso de que .NET no sepa cómo inicializar el tipo.

 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler([Resolve Function]); 
4

Algunas otras respuestas han mencionado la falta de claridad en el nombre del método IsAssignableFrom. Estoy de acuerdo, y como resultado lo estaba usando de la manera incorrecta.

Pruebe un poco de experimentar con invirtiendo los objetos en su código y vea si funciona. Por ejemplo:

Reemplazar:

if (typeof(IPlugin).IsAssignableFrom(t)) 

con:

if (t.IsAssignableFrom(typeof(IPlugin))) 

Al hacer esto, no solamente tengo que trabajar, pero comenzaron a entender lo que realmente hace este método.

+0

En realidad, esto suena incorrecto. De acuerdo con los documentos (https://msdn.microsoft.com/pl-pl/library/system.type.isassignablefrom(v=vs.110).aspx) true se devuelve cuando * la instancia actual es una interfaz que c implementa *. Esto hace 'i.IsAssignableFrom (t)' válido en este escenario. –

3

Tuve el mismo problema cuando la interfaz se definió en un ensamblaje separado para el tipo de implementación. Iterar y cargar ensamblajes desde la carpeta raíz que contenía dlls con clases Y dll con interfaz resultó en una falta de coincidencia de tipos como se mencionó anteriormente.

Una solución era cambiar LoadFrom()-LoadFile() El método LoadFrom tiene algunas desventajas, y que es uno de ellos:

Si ya está cargado un conjunto con la misma identidad, LoadFrom devuelve el ensamblado cargado incluso si una ruta diferente fue especificada

Otra manera de superar esto es colocar todas las DLL con los tipos de aplicación de interfaz en carpeta separada y no copiar ensamblaje de referencia (CopyLocal = False) de modo Assembly.LoadFrom no se puede cargar DLL de interfaz que contiene en la memoria.

+0

Me encontré en esta misma situación y esto me sirvió de algo. – Larry

Cuestiones relacionadas