with net method español create c# .net reflection

c# - net - IsAssignableFrom() devuelve falso cuando debería devolver true



reflection c# español (6)

Estoy trabajando en un sistema de complemento que carga los archivos .dll contenidos en una carpeta específica. Luego utilizo la reflexión para cargar los ensamblajes, recorrer los tipos que contienen e identificar los que implementan mi interfaz IPlugin .

Estoy revisando esto con un código similar al siguiente:

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

Por algún motivo, IsAssignableFrom () sigue devolviendo false cuando debería devolver true. He intentado reemplazar la t explícitamente dándole un tipo que debería pasar, y funciona bien, pero por alguna razón no está funcionando con los tipos que se devuelven desde el conjunto 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 de algo que pueda causar este tipo de comportamiento?

Gracias


Trabajo en Java que tiene el mismo método de API y no puedo dejar de pensar en 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.


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 sobre los que se está iterando.

Te sugiero que imprimas:

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.


El nombre del método Type.IsAssignableFrom es vago y confuso cuando se lo aplica a probar la herencia o detectar implementaciones de interfaz. El siguiente contenedor para estos propósitos 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, como:

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

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


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 un resolver ensamblador en caso de que .NET no sepa cómo inicializar el tipo.

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


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.

Intente experimentar un poco revertiendo 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 solo lo conseguí, sino que comencé a entender qué hace realmente este método.


Tuve el mismo problema cuando la interfaz se definió en un ensamblaje separado para el tipo de implementación. La iteración y la carga de ensamblajes desde la carpeta raíz que contenía dlls con clases Y dll con interfaz resultó en un desajuste de tipo como se mencionó anteriormente.

Una solución fue cambiar LoadFrom() a LoadFile() El método LoadFrom tiene algunas desventajas y esa es una de ellas:

Si ya se ha cargado un ensamblado con la misma identidad, LoadFrom devuelve el ensamblaje cargado incluso si se especificó una ruta diferente.

Otra forma de solucionar esto es colocar todos los archivos DLL con los tipos que implementan la interfaz en una carpeta separada y no copiar el conjunto referenciado ( CopyLocal = False ) para que Assembly.LoadFrom no cargue dll que contenga la interfaz en la memoria.