TypeLoadException dice ‘no implementación’, pero está implementado

Tengo una falla muy extraña 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á ahí en la clase DummyItem , e incluso he recomstackdo una versión con escrituras en el registro de eventos solo para asegurarme de que no se trata de un problema de implementación / control de versiones. Lo extraño es que el código de llamada ni siquiera llama al método SetShort .

NOTA – Si esta respuesta no lo ayuda, tómese el tiempo para desplazarse hacia abajo a través de las otras respuestas que la gente ha agregado desde entonces.

Respuesta corta

Esto puede suceder si agrega un método a una interfaz en un ensamblaje y luego a una clase implementadora en otro ensamblaje, pero reconstruye el ensamblaje de implementación sin hacer referencia a la nueva versión del ensamblaje de interfaz.

En este caso, DummyItem implementa una interfaz de otro ensamblaje. 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 conjunto de interfaz. Entonces, el método SetShort está efectivamente allí, pero sin la salsa mágica que lo vincula al método equivalente en la interfaz.

Respuesta larga

Si quieres intentar reproducir esto, prueba lo siguiente:

  1. Cree un proyecto de biblioteca de clase: InterfaceDef, agregue solo una clase y compile:

     public interface IInterface { string GetString(string key); //short GetShort(string key); } 
  2. Cree un proyecto de biblioteca de segunda clase: Implementación (con una solución por separado), copie InterfaceDef.dll en el directorio del proyecto y agregue como referencia de archivo, agregue solo una clase y compile:

     public class ImplementingClass : IInterface { #region IInterface Members public string GetString(string key) { return "hello world"; } //public short GetShort(string key) //{ // return 1; //} #endregion } 
  3. 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 en el método Main:

      IInterface test = new ImplementingClass(); string s = test.GetString("dummykey"); Console.WriteLine(s); Console.ReadKey(); 
  4. Ejecuta el código una vez, la consola dice “hola mundo”

  5. Descomente el código en los dos proyectos dll y vuelva a generar: copie los dos dlls nuevamente en el proyecto ClientCode, vuelva a generar e intente ejecutar nuevamente. TypeLoadException se produce al intentar crear una instancia de ImplementingClass.

Además de lo que la propia respuesta del asker ya indicó, puede valer la pena señalar lo siguiente. La razón por la que esto ocurre 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 que:

 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 definía una clase que el método en el mensaje de error usaba. La ejecución de PEVerify arrojó un error más útil: “El sistema no puede encontrar el archivo especificado”.

Me encontré con el mismo mensaje y aquí está lo que hemos encontrado: utilizamos dlls de terceros en nuestro proyecto. Después de que salió una nueva versión de los mismos, cambiamos nuestro proyecto para señalar el nuevo conjunto de DLL y comstackrlo 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 todavía no tuvimos suerte. Necesitábamos un tiempo para detectar (utilizando el Examinador de objetos) que el tipo de devolución del método en el mensaje de error era un tipo completamente nuevo de un ensamblaje nuevo 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 usamos el método en cuestión.
  • Lo que me lleva a la pregunta: si esta excepción se produce en cualquier caso, ¿por qué el comstackdor no la recoge?

Recibí este error en la siguiente situación.

  • Ambos ensamblajes A y B hacen referencia a System.Web.Mvc Version 3.0.0.0
  • El ensamblado A hizo referencia al ensamblado B y tenía clases que implementaban interfaces del ensamblado B con métodos que devolvían clases de System.Web.Mvc.
  • Conjunto A actualizado a System.Web.Mvc versión 4.0.0.0
  • El ensamblado C ejecutaba el siguiente código (FertPin.Classes.Contact estaba contenido en el ensamblaje A):

var target = Assembly.GetAssembly(typeof(FertPin.Classes.Contact));

La solución para mí fue actualizar la referencia System.Web.Mvc en el ensamblaje B a 4.0.0.0. Parece obvio ahora!

¡Gracias al cartel original!

La otra vez que puede obtener este error es si tiene una versión incorrecta de un ensamblaje firmado. No es el síntoma normal de esta causa, pero aquí estaba el escenario donde lo obtuve

  • un proyecto asp.net contiene el ensamblaje A y el ensamblaje B, B es llamado con fuerza

  • el ensamblaje A usa el activador.CreateInstance para cargar el ensamblaje C (es decir, no hay ninguna referencia a C que se construye por separado)

  • C se construyó haciendo referencia a una versión anterior del ensamblado B que actualmente está presente

Espero que eso ayude a alguien, me tomó años resolver esto.

También tuve este error, fue causado por un exe de cualquier CPU que hace referencia a cualquier ensamblado de CPU que a su vez hace referencia a un ensamblado x86.

La excepción se quejaba de un método en una clase en MyApp.Implementations (Cualquier CPU), que derivaba MyApp.Interfaces (Cualquier CPU), pero en fuslogvw.exe encontré una excepción oculta ‘bash de cargar el progtwig con un formato incorrecto’ de MyApp .CommonTypes (x86) que utilizan ambos.

Lo obtuve con una dependencia de proyecto en forma de “diamante”:

  • El Proyecto A usa el Proyecto B y el Proyecto D
  • El Proyecto B usa el Proyecto D

Recopilé el proyecto A pero no el Proyecto B, lo que permitió que el Proyecto B “inyectara” la versión anterior del proyecto D dll

Me encontré con esto cuando cambié el nombre de un proyecto (y el nombre del ensamblado), que dependía de un proyecto ASP.NET. Tipos en el proyecto web implementadas interfaces en el ensamblado dependiente. A pesar de ejecutar Clean Solution en el menú Build, el ensamblado con el nombre anterior permaneció en la carpeta bin , y cuando se ejecutó mi proyecto web

 var types = AppDomain.CurrentDomain. GetAssemblies(). ToList(). SelectMany( s => s.GetTypes() /* exception thrown in this call */ ) ; 

se lanzó la excepción anterior, quejándose de que los métodos de interfaz en los tipos de web implementados no se implementaron realmente. La eliminación manual del ensamblaje en la carpeta bin del proyecto web resolvió el problema.

Sigo volviendo a esto … Muchas de las respuestas aquí hacen un gran trabajo explicando cuál es el problema, pero no cómo solucionarlo.

La solución a esto es eliminar manualmente los archivos bin en el directorio de proyectos publicados. Limpiará todas las referencias y forzará al proyecto a usar las últimas DLL.

No sugiero utilizar la función de eliminación de las herramientas de publicación porque esto tiende a deshacerse de IIS.

Tengo otra solución esotérica a este mensaje de error. Actualicé mi framework de destino de .Net 4.0 a 4.6, y el proyecto de prueba de mi unidad me dio el error “System.TypeLoadException … no tiene una implementación” cuando intenté comstackr. También dio un segundo mensaje de error sobre el mismo método supuestamente no implementado que decía “Falló inesperadamente la tarea ‘BuildShadowTask'”. Ninguno de los consejos aquí parecía ayudar, así que busqué “BuildShadowTask” y encontré una publicación en MSDN que me llevó a utilizar un editor de texto para eliminar estas líneas del archivo csproj del proyecto de prueba de la unidad.

    

Después de eso, ambos errores desaparecieron y el proyecto se construyó.

Encontré este error en un contexto en el que estaba usando Autofac y una gran cantidad de carga dinámica de ensamblaje.

Al realizar una operación de resolución Autofac, el tiempo de ejecución no podría cargar uno de los ensamblajes. El mensaje de error se quejó de que el Method 'MyMethod' in type 'MyType' from assembly 'ImplementationAssembly' does not have an implementation . Los síntomas se produjeron al ejecutar en una máquina virtual Windows Server 2012 R2, pero no se produjeron en máquinas virtuales con Windows 10 o Windows Server 2016.

ImplementationAssembly referencia a System.Collections.Immutable 1.1.37, y contenía implementaciones de una IMyInterface , que se definió en un IMyInterface separado. DefinitionAssembly referenciado System.Collections.Immutable 1.1.36.

Los métodos de IMyInterface que fueron “no implementados” tenían parámetros de tipo IImmutableDictionary , que se define en System.Collections.Immutable .

La copia real de System.Collections.Immutable encuentra en el directorio del progtwig era la versión 1.1.37. En mi VM de Windows Server 2012 R2, el GAC contenía una copia de System.Collections.Immutable 1.1.36. En Windows 10 y Windows Server 2016, el GAC contenía una copia de System.Collections.Immutable 1.1.37. El error de carga solo se produjo cuando el GAC contenía la versión anterior de la DLL.

Por lo tanto, la causa raíz de la falla de carga del ensamblaje fueron las referencias no coincidentes a System.Collections.Immutable . La definición e implementación de la interfaz tenía firmas de métodos de aspecto idéntico, pero en realidad dependía de diferentes versiones de System.Collections.Immutable , lo que significaba que el tiempo de ejecución no consideraba que la clase de implementación coincidiera con la definición de la interfaz.

Agregar el siguiente redireccionamiento de enlace a mi archivo de configuración de la aplicación solucionó el problema:

     

También recibí este error cuando anteriormente habilité Cobertura de código durante la prueba de unidad para uno de los ensamblajes. Por alguna razón, Visual Studio “almacenó en búfer” la versión anterior de esta DLL en particular, aunque la había actualizado para implementar una nueva versión de la interfaz. La desactivación de la cobertura del código eliminó el error.

Otra explicación para este tipo de problema que involucra a C ++ administrado.

Si intenta resguardar una interfaz definida en un ensamblado creado utilizando C ++ administrado que tiene una firma especial, obtendrá la excepción cuando se cree el código auxiliar.

Esto es cierto para Rhino Mocks y probablemente cualquier marco mocking que use System.Reflection.Emit .

 public interface class IFoo { void F(long bar); }; public ref class Foo : public IFoo { public: virtual void F(long bar) { ... } }; 

La definición de interfaz obtiene la siguiente firma:

 void F(System.Int32 modopt(IsLong) bar) 

Tenga en cuenta que el tipo de C ++ se mapea a System.Int32 (o simplemente int en C #). Es el modo oscuro algo obscuro que está causando el problema según lo declarado por Ayende Rahien en la lista de correo de Rhino Mocks .

Este error también puede producirse si un ensamblaje se carga utilizando Assembly.LoadFrom (String) y hace referencia a un ensamblaje que ya se cargó usando Assembly.Load (Byte []).

Por ejemplo, ha incorporado los ensamblados a los que hace referencia la aplicación principal como recursos, pero su aplicación carga complementos de una carpeta específica.

En lugar de usar LoadFrom, debe usar Load. El siguiente código hará el trabajo:

 private static Assembly LoadAssemblyFromFile( String filePath ) { using( Stream stream = File.OpenRead( filePath ) ) { if( !ReferenceEquals( stream, null ) ) { Byte[] assemblyData = new Byte[stream.Length]; stream.Read( assemblyData, 0, assemblyData.Length ); return Assembly.Load( assemblyData ); } } return null; } 

Acabo de actualizar una solución de MVC3 a MVC5, y comencé a recibir la misma excepción de mi proyecto de prueba de la Unidad.

Comprobé todas las referencias en busca de archivos antiguos, eventualmente descubrí que necesitaba hacer algunos bindingRedirects para Mvc, en mi proyecto de prueba de unidad.

 < ?xml version="1.0" encoding="utf-8" ?>                   

En mi caso, ayudó a restablecer la WinForms Toolbox.

Obtuve la excepción al abrir un Form en el diseñador; sin embargo, comstackr y ejecutar el código era posible y el código se comportó como se esperaba. La excepción ocurrió en un UserControl local que implementa una interfaz de una de las bibliotecas a las que me he referido. El error surgió después de que se actualizó esta biblioteca.

Este UserControl se incluyó en la caja de herramientas de WinForms. Probablemente, Visual Studio mantuvo una referencia en una versión obsoleta de la biblioteca o estaba almacenando en caché una versión obsoleta en alguna parte.

Así es como me recuperé de esta situación:

  1. Haga clic derecho en WinForms Toolbox y haga clic en Reset Toolbox en el menú contextual. (Esto elimina elementos personalizados de la Caja de herramientas).
    En mi caso, los elementos de Toolbox se restauraron a su estado predeterminado; sin embargo, la flecha del puntero faltaba en la Caja de herramientas.
  2. Cierre Visual Studio.
    En mi caso, Visual Studio terminó con una excepción de violación y se canceló.
  3. Reinicie Visual Studio.
    Ahora todo está funcionando sin problemas.

FWIW, obtuve esto cuando había un archivo de configuración que redirigía a una versión inexistente de un ensamblado al que se hace referencia. ¡Fusion registra la victoria!

Obtuve este error porque tenía una clase en un ensamblado ‘C’ que estaba en la versión 4.5 del framework, implementando una interfaz en el ensamblado ‘A’ que estaba en la versión 4.5.1 del framework y que sirve como la clase base para ensamblar ‘B’ que también estaba en la versión 4.5.1 del marco. El sistema arrojó la excepción al intentar cargar el ensamblaje ‘B’. Además, había instalado algunos paquetes nuget dirigidos a .NET 4.5.1 en los tres ensamblajes. Por alguna razón, a pesar de que las referencias nuget no se mostraban en el ensamblado ‘B’, se estaba construyendo con éxito.

Resultó que el problema real era que las asambleas estaban haciendo referencia a diferentes versiones de un paquete nuget que contenía la interfaz y la firma de la interfaz había cambiado entre las versiones.

En mi caso, anteriormente había hecho referencia a un proyecto de mylib en una carpeta de hermanos fuera del repository, llamémoslo v1.0 .

 |-- myrepo | |-- consoleApp | |-- submodules | |-- mylib (submoduled v2.0) |-- mylib (stale v1.0) 

Más tarde lo hice correctamente y lo utilicé a través de un submódulo de git. Vamos a llamar a ese v2.0 . Sin embargo, una consoleApp proyecto no se actualizó correctamente. Todavía estaba haciendo referencia al viejo proyecto v1.0 fuera de mi proyecto git.

De manera confusa , aunque el *.csproj era claramente incorrecto y apuntaba a v1.0 , ¡el Visual Studio IDE mostró la ruta como el proyecto v2.0 ! F12 para inspeccionar la interfaz y la clase también fue a la versión v2.0 .

El ensamblado colocado en la carpeta bin por el comstackdor era la versión v1.0 , de ahí el dolor de cabeza.

El hecho de que el IDE me mintiera hizo que fuera más difícil darse cuenta del error.

Solución : eliminó las referencias del proyecto de ConsoleApp y las volvió a listar.

Sugerencia general: vuelva a comstackr todos los ensamblajes desde cero (cuando sea posible, por supuesto, no para los paquetes nuget) y verifique los sellos de fecha y hora en la carpeta bin\debug . Cualquier ensamblaje anticuado es tu problema.

Me enfrenté casi al mismo problema. Me estaba rascando la cabeza lo que está causando este error. Hice una verificación cruzada, todos los métodos fueron implementados.

En Google, obtuve este enlace, entre otros. Basado en el comentario de @Paul McLink, estos dos pasos resolvieron el problema.

  1. Reiniciar Visual Studio
  2. Limpiar, construir (reconstruir)

y el error desapareció

Reiniciar VS Plugin

Gracias Paul 🙂

Espero que esto ayude a alguien que encuentre este error 🙂

También encontré este problema mientras ejecutaba mis pruebas de unidad. La aplicación funcionó bien y sin errores. La causa del problema en mi caso fue que había desactivado la construcción de los proyectos de prueba. Rehabilitar la construcción de mis proyectos de prueba resolvió los problemas.

Vi esto en Visual Studio Pro 2008 cuando dos proyectos crearon ensamblajes con el mismo nombre, uno de clase SDF.dll y uno que hacía referencia a la lib con el nombre de ensamblaje sdf.exe. Cuando cambié el nombre del ensamblado de referencia, la excepción desapareció

Aquí está mi opinión sobre este error.

extern un método extern , pero mi pegado fue defectuoso. El DllImportAttribute se puso en una línea comentada.

 /// (removed for brevity lol)[DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsWindowVisible(IntPtr hWnd); 

Asegurar que el atributo se haya incluido realmente en la fuente solucionó el problema.

Obtuve esto en un servicio WCF debido a que tenía un tipo de comstackción x86 seleccionado, lo que causaba que el bisn viviera en bin \ x86 en lugar de bin. Al seleccionar Cualquier CPU, las DLL recomstackdas se dirigieron a las ubicaciones correctas (en primer lugar, no detallaré cómo sucedió esto).

Esto simplemente significa que el proyecto de implementación está desactualizado en mis casos. La DLL que contiene la interfaz fue reconstruida pero la dll de implementación estaba obsoleta.

Yo tuve el mismo problema. Descubrí que mi ensamblaje, que está cargado por el progtwig principal, tenía algunas referencias con “Copiar local” establecido en verdadero. Estas copias locales de referencias buscaban otras referencias en la misma carpeta, que no existían porque el “Copiar local” de otras referencias se estableció en falso. Después de borrar las referencias copiadas “accidentalmente”, el error desapareció porque el progtwig principal se configuró para buscar ubicaciones correctas de referencias. Aparentemente, las copias locales de las referencias arruinaron la secuencia de llamadas porque se usaron estas copias locales en lugar de las originales presentes en el progtwig principal.

El mensaje para llevar a casa es que este error aparece debido al enlace faltante para cargar el ensamblaje requerido.

En mi caso, estaba intentando usar TypeBuilder para crear un tipo. TypeBuilder.CreateType lanzó esta excepción. Finalmente me di cuenta de que necesitaba agregar MethodAttributes.Virtual a los atributos al llamar a TypeBuilder.DefineMethod para un método que ayuda a implementar una interfaz. Esto es porque sin este indicador, el método no implementa la interfaz, sino un nuevo método con la misma firma en su lugar (incluso sin especificar MethodAttributes.NewSlot ).

Como una adición: esto también puede ocurrir si actualiza un paquete nuget que se utilizó para generar un ensamblaje de falsificaciones. Supongamos que instala V1.0 de un paquete nuget y crea un ensamblaje falso “fakeLibrary.1.0.0.0.Fakes”. A continuación, actualice a la versión más nueva del paquete nuget, digamos v1.1 que agregó un nuevo método a una interfaz. La biblioteca Fakes todavía está buscando v1.0 de la biblioteca. Simplemente elimine el ensamblaje falso y vuelva a generarlo. Si ese era el problema, esto probablemente lo arreglaría.

Recibí este error después de una reciente actualización de Windows. Tenía una clase de servicio configurada para heredar desde una interfaz. La interfaz contenía una firma que devolvía un ValueTuple, una característica bastante nueva en C #.

Todo lo que puedo adivinar es que la actualización de Windows instaló una nueva, pero incluso haciendo referencias explícitas, actualizando redireccionamientos de enlaces, etc … El resultado final fue simplemente cambiar la firma del método a algo “estándar”, supongo que se podría decir.