TypeLoadException dice "sin implementación", pero está implementada
Tengo un error muy extraño en nuestra máquina de prueba. El error es:
System.TypeLoadException: Method 'SetShort' in type 'DummyItem' from assembly 'ActiveViewers (...)' does not have an implementation.
Simplemente no puedo entender por qué. SetShort
está allí en la DummyItem
clase, e incluso he vuelto a compilar una versión con escrituras en el registro de eventos solo para asegurarme de que no sea un problema de implementación/versiones. Lo extraño es que el código de llamada ni siquiera llama al SetShort
método.
NOTA : si esta respuesta no le ayuda, tómese el tiempo para desplazarse hacia abajo por las otras respuestas que las personas han agregado desde entonces.
respuesta muy corta
Elimine todos sus directorios bin
y obj
y reconstruya todo. Las versiones de las DLL no coinciden.
Respuesta corta
Esto puede suceder si agrega un método a una interfaz en un ensamblado y luego a una clase de implementación en otro ensamblado, pero reconstruye el ensamblado de implementación sin hacer referencia a la nueva versión del ensamblado de la interfaz.
En este caso, DummyItem implementa una interfaz de otro ensamblado. El método SetShort se agregó recientemente tanto a la interfaz como a DummyItem, pero el ensamblaje que contiene DummyItem se reconstruyó haciendo referencia a la versión anterior del ensamblaje de la interfaz. Entonces, el método SetShort está efectivamente ahí, pero sin la salsa mágica que lo vincula al método equivalente en la interfaz.
Respuesta larga
Si desea intentar reproducir esto, intente lo siguiente:
Cree un proyecto de biblioteca de clases: InterfaceDef, agregue solo una clase y cree:
public interface IInterface { string GetString(string key); //short GetShort(string key); }
Cree un proyecto de biblioteca de segunda clase: implementación (con solución separada), copie InterfaceDef.dll en el directorio del proyecto y agréguelo como archivo de referencia, agregue solo una clase y cree:
public class ImplementingClass : IInterface { #region IInterface Members public string GetString(string key) { return "hello world"; } //public short GetShort(string key) //{ // return 1; //} #endregion }
Cree un tercer proyecto de consola: ClientCode, copie los dos dlls en el directorio del proyecto, agregue referencias de archivos y agregue el siguiente código al método Main:
IInterface test = new ImplementingClass(); string s = test.GetString("dummykey"); Console.WriteLine(s); Console.ReadKey();
Ejecute el código una vez, la consola dice "hola mundo"
Descomente el código en los dos proyectos dll y reconstruya: copie los dos dll nuevamente en el proyecto ClientCode, reconstruya e intente ejecutar nuevamente. TypeLoadException ocurre al intentar crear una instancia de ImplementingClass.
Además de lo que ya indicó la propia respuesta del autor de la pregunta, puede valer la pena señalar lo siguiente. La razón por la que esto sucede es porque es posible que una clase tenga un método con la misma firma que un método de interfaz sin implementar ese método. El siguiente código ilustra eso:
public interface IFoo
{
void DoFoo();
}
public class Foo : IFoo
{
public void DoFoo() { Console.WriteLine("This is _not_ the interface method."); }
void IFoo.DoFoo() { Console.WriteLine("This _is_ the interface method."); }
}
Foo foo = new Foo();
foo.DoFoo(); // This calls the non-interface method
IFoo foo2 = foo;
foo2.DoFoo(); // This calls the interface method
Obtuve esto cuando mi aplicación no tenía una referencia a otro ensamblado que definiera una clase que usaba el método en el mensaje de error. Al ejecutar PEVerify se produjo un error más útil: "El sistema no puede encontrar el archivo especificado".
Me encontré con el mismo mensaje y esto es lo que encontramos: Usamos archivos DLL de terceros en nuestro proyecto. Después de que salió una nueva versión de estos, cambiamos nuestro proyecto para que apunte al nuevo conjunto de dlls y lo compilamos con éxito.
La excepción se produjo cuando intenté instalar una de sus clases interconectadas durante el tiempo de ejecución. Nos aseguramos de que todas las demás referencias estuvieran actualizadas, pero aún así no tuvimos suerte. Necesitamos un tiempo para detectar (usando el Explorador de objetos) que el tipo de retorno del método en el mensaje de error era un tipo completamente nuevo de un ensamblado nuevo y sin referencia.
Agregamos una referencia al ensamblaje y el error desapareció.
- El mensaje de error era bastante engañoso, pero apuntaba más o menos en la dirección correcta (método correcto, mensaje incorrecto).
- La excepción ocurrió aunque no utilizamos el método en cuestión.
- Lo que me lleva a la pregunta: si se produce esta excepción en cualquier caso, ¿por qué el compilador no la detecta?