TypeLoadException говорит "Нет реализации", но он реализован

у меня очень странная ошибка на нашей тестовой машине. Ошибка:

System.TypeLoadException: Method 'SetShort' in type 'DummyItem' from assembly 'ActiveViewers (...)' does not have an implementation.

Я просто не могу понять, почему. SetShort есть в DummyItem class, и я даже перекомпилировал версию с записями в журнал событий, чтобы убедиться, что это не проблема развертывания/управления версиями. Странно то, что вызывающий код даже не вызывает SetShort метод.

30 ответов


Примечание - если этот ответ не поможет вам, пожалуйста, прокрутите вниз через другие ответы, которые люди добавили с тех пор.

короткий ответ:

Это может произойти, если вы добавляете метод к интерфейсу в одной сборке, а затем к реализующему классу в другой сборке, но перестраиваете реализующую сборку без ссылки на новую версию сборки интерфейса.

В этом случае, DummyItem реализует интерфейс из другой сборки. Метод SetShort недавно был добавлен как к интерфейсу, так и к DummyItem, но сборка, содержащая DummyItem, была перестроена, ссылаясь на предыдущую версию сборки интерфейса. Таким образом, метод SetShort эффективно существует, но без волшебного соуса, связывающего его с эквивалентным методом в интерфейсе.

ответ

Если вы хотите попробовать воспроизвести, попробуйте следующий:

  1. создайте проект библиотеки классов: InterfaceDef, добавьте только один класс и создайте:

    public interface IInterface
    {
        string GetString(string key);
        //short GetShort(string key);
    }
    
  2. создайте проект библиотеки второго класса: реализация (с отдельным решением), скопируйте InterfaceDef.dll в каталог проекта и добавить в качестве ссылки на файл, добавить только один класс и построить:

    public class ImplementingClass : IInterface
    {
        #region IInterface Members
        public string GetString(string key)
        {
            return "hello world";
        }
    
        //public short GetShort(string key)
        //{
        //    return 1;
        //}
        #endregion
    }
    
  3. создайте третий, консольный проект: ClientCode, скопируйте две библиотеки DLL в каталог проекта, добавьте ссылки на файл и добавьте следующий код в метод Main:

     IInterface test = new ImplementingClass();
     string s = test.GetString("dummykey");
     Console.WriteLine(s);
     Console.ReadKey();
    
  4. запустите код один раз, консоль говорит "hello world"

  5. раскомментируйте код в двух проектах dll и перестройте - скопируйте две библиотеки DLL обратно в проект ClientCode, перестройте и повторите попытку. Исключение typeloadexception возникает при попытке инстанцировать ImplementingClass.


в дополнение к тому, что уже указано в собственном ответе спрашивающего, может быть стоит отметить следующее. Причина этого заключается в том, что класс может иметь метод с той же сигнатурой, что и метод интерфейса, без реализации этого метода. Следующий код иллюстрирует это:

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

Я получил это, когда мое приложение не имело ссылки на другую сборку, определяющую класс, который использовал метод в сообщении об ошибке. Запуск PEVerify дал более полезную ошибку: "система не может найти указанный файл."


я наткнулся на такое же сообщение и вот что мы нашли: Мы используем сторонние библиотеки DLL в нашем проекте. После выхода нового выпуска мы изменили наш проект, чтобы указать на новый набор DLL и успешно скомпилировали.

исключение было вызвано, когда я попытался создать экземпляр одного из их сопряженных классов во время выполнения. Мы убедились, что все остальные ссылки были актуальными, но все равно не повезло. Нам нужно было некоторое время, чтобы определить (используя браузер объектов), что возвращаемый тип метода в сообщении об ошибке был совершенно новым типом из новой, не прошедшей проверку сборки.

мы добавили ссылку на сборку и ошибка исчезла.

  • сообщение об ошибке было довольно вводящим в заблуждение, но указывало более или менее в правильном направлении (правильный метод, неправильное сообщение).
  • исключение ocurred, хотя мы не использовали рассматриваемый метод.
  • что приводит меня к вопросу: если этот исключение в любом случае, почему компилятор не берет его?

Я получил эту ошибку в следующей ситуации.

  • обе сборки A и B ссылаются на систему.Сеть.В MVC Версии 3.0.0.0
  • сборка a ссылалась на сборку B и имела классы, которые реализовали интерфейсы из сборки B с методами, которые возвращали классы из системы.Сеть.В MVC.
  • сборка a обновлена до System.Сеть.В MVC Версии 4.0.0.0
  • сборка C выполнила код ниже (FertPin.Занятия.Контакт содержался в агрегате A):

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

исправление для меня было обновление системы.Сеть.Ссылка Mvc в сборке B на 4.0.0.0. Теперь это кажется очевидным!

благодаря оригинальному плакату!


в другой раз вы можете получить эту ошибку, если у вас есть неправильная версия подписанной сборки. Это не нормальный симптом для этой причины, но вот сценарий, где я его получил

  • an asp.net проект содержит сборку A и сборку B, B имеет строгое имя

  • в сборке A используется активатор.CreateInstance для загрузки сборки C (т. е. нет ссылки на C, которая построена отдельно)

  • C был построен ссылка на старую версию сборки B, чем в настоящее время

надеюсь, что это поможет кому - то-мне потребовались века, чтобы понять это.


У меня тоже была эта ошибка, она была вызвана любым CPU exe, ссылающимся на любые сборки CPU, которые, в свою очередь, ссылались на сборку x86.

исключение пожаловалось на метод в классе в MyApp.Реализации (любой процессор), который получил MyApp.Интерфейсы (любой процессор), но в fuslogvw.exe я нашел скрытую "попытку загрузки программы с неправильным форматом" исключение из MyApp.CommonTypes (x86), который используется обоими.


Я получил это с зависимостью проекта в форме "алмаза":

  • проект A использует проект B и проект D
  • проект B использует проект D

Я перекомпилировал проект A, но не проект B, что позволило проекту B "внедрить" старую версию dll проекта D


я столкнулся с этим, когда я переименовал проект (и имя сборки), от которого зависело ASP.NET проект. Типы в веб-проекте реализованы интерфейсы в зависимой сборке. Несмотря на выполнение чистого решения из меню сборки, Сборка с предыдущим именем осталась в bin папка, и когда мой веб-проект, выполненный

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

вышеприведенное исключение было вызвано, жалуясь, что методы интерфейса в реализующих веб-типах фактически не были выполненный. Удаление сборки в веб-проекте вручную bin папка решить проблему.


Я продолжаю возвращаться к этому... Многие из ответов здесь отлично объясняют, в чем проблема, но не как ее исправить.

решение этой проблемы заключается в ручном удалении файлов bin в опубликованном каталоге проектов. Он очистит все ссылки и заставит проект использовать последние библиотеки DLL.

Я не предлагаю использовать функцию удаления инструментов публикации, потому что это имеет тенденцию выбрасывать IIS.


У меня есть еще одно эзотерическое решение этого сообщения об ошибке. Я обновил свою целевую платформу с .Net 4.0 до 4.6, и мой проект модульного тестирования дал мне "систему".исключение TypeLoadException...не имеет реализации" ошибка, когда я пытался построить. Он также дал второе сообщение об ошибке о том же якобы не реализованном методе, который сказал: "Задача" BuildShadowTask " неожиданно не удалась."Ни один из советов здесь, казалось, не помог, поэтому я искал "BuildShadowTask" и нашел сообщение на MSDN что привело меня к использованию текстового редактора для удаления этих строк из файла csproj проекта модульного теста.

<ItemGroup>
  <Shadow Include="Test References\MyProject.accessor" />
</ItemGroup>

после этого обе ошибки исчезли, и проект был построен.


я столкнулся с этой ошибкой в контексте, где я использовал Autofac и много динамической загрузки сборки.

при выполнении операции разрешения Autofac среда выполнения не сможет загрузить одну из сборок. Сообщение об ошибке пожаловалось, что Method 'MyMethod' in type 'MyType' from assembly 'ImplementationAssembly' does not have an implementation. Симптомы возникли при запуске на виртуальной машине Windows Server 2012 R2, но сделали не происходят на Windows 10 или Windows Server 2016 VMs.

ImplementationAssembly ссылка System.Collections.Immutable 1.1.37, и содержащиеся реализации IMyInterface<T1,T2> интерфейс, который был определен в отдельный DefinitionAssembly. DefinitionAssembly ссылка System.Collections.Immutable 1.1.36.

методы IMyInterface<T1,T2> которые были "не реализованы" имели параметры типа IImmutableDictionary<TKey, TRow>, которая определена в System.Collections.Immutable.

фактическая копия System.Collections.Immutable в каталоге программы найдена версия 1.1.37. На моей виртуальной машине Windows Server 2012 R2 GAC содержал копию System.Collections.Immutable 1.1.36. В Windows 10 и Windows Server 2016 GAC содержит копию из System.Collections.Immutable 1.1.37. Ошибка загрузки произошла только тогда, когда GAC содержал более старую версию DLL.

Итак, основной причиной сбоя загрузки сборки были несоответствующие ссылки на System.Collections.Immutable. Определение и реализация интерфейса имели идентичные сигнатуры методов, но на самом деле зависели от разных версий System.Collections.Immutable, что означало, что среда выполнения не рассматривала класс реализации для соответствия определению интерфейса.

добавить после перенаправления привязки к моему файлу конфигурации приложения Исправлена проблема:

<dependentAssembly>
        <assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-1.1.37.0" newVersion="1.1.37.0" />
</dependentAssembly>

Я также получил эту ошибку, когда я ранее включил покрытие кода во время модульного тестирования для одной из сборок. По какой-то причине Visual Studio "буферизовала" старую версию этой конкретной DLL, хотя я обновил ее для реализации новой версии интерфейса. Отключение покрытия кода избавило от ошибки.


другое объяснение этого типа проблемы, связанной с управляемым C++.

если вы попытаетесь заглушки интерфейс, определенный в сборке, созданной с помощью управляемого C++, который имеет специальную подпись, вы получите исключение при создании стаб.

это верно для Rhino Mocks и, вероятно, любой насмешливый фреймворк, который использует System.Reflection.Emit.

public interface class IFoo {
  void F(long bar);
};

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

определение интерфейса получает следующую подпись:

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

обратите внимание, что тип C++ long карты System.Int32 (или просто int в C#). Это несколько неясное modopt это вызывает проблему как заявил Ayende Rahien на носорога издевается рассылки .


эта ошибка также может возникать, если сборка загружается с помощью сборки.LoadFrom(String) и ссылается на сборку, которая уже была загружена с помощью сборки.Загрузить(Байт[]).

например, у вас есть встроенные сборки основного приложения в качестве ресурсов, но ваше приложение загружает плагины из определенной папки.

вместо использования LoadFrom вы должны использовать Load. Следующий код будет выполнять эту работу:

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;
}

Я только что обновил решение с MVC3 до MVC5 и начал получать то же исключение из моего проекта модульного тестирования.

проверил все ссылки, ищущие старые файлы, eventualy обнаружил, что мне нужно сделать некоторые bindingRedirects для Mvc в моем проекте модульного тестирования.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

в моем случае это помогло сбросить набор инструментов WinForms.

Я получил исключение при открытии Form в конструкторе; однако компиляция и запуск кода были возможны, и код вел себя так, как ожидалось. Исключение произошло в локальном UserControl реализация интерфейса из одной из моих ссылочных библиотек. Ошибка возникла после обновления этой библиотеки.

этой UserControl был указан в панели инструментов WinForms. Вероятно, Visual Studio сохранила ссылку на устаревшая версия библиотеки или кэширование устаревшей версии где-то.

вот как я оправился от этой ситуации:

  1. щелкните правой кнопкой мыши на панели инструментов WinForms и нажмите на Reset Toolbox в контекстном меню. (это удаляет пользовательские элементы из панели инструментов).
    в моем случае элементы Toolbox были восстановлены в состояние по умолчанию; однако стрелка указателя отсутствовала в Toolbox.
  2. Закрыть Visual Студия.
    в моем случае Visual Studio завершается с исключением нарушения и прерывается.
  3. Перезапустите Visual Studio.
    теперь все идет гладко.

FWIW, я получил это, когда был файл конфигурации, перенаправленный на несуществующую версию ссылочной сборки. Fusion журналы для победы!


Я получил эту ошибку, потому что у меня был класс в сборке "C", которая была на версии 4.5 фреймворка, реализуя интерфейс в сборке "A", которая была на версии 4.5.1 фреймворка и служила базовым классом для сборки "B", которая также была на версии 4.5.1 фреймворка. Система выдала исключение при попытке загрузить сборку "B". Кроме того, я установил некоторые пакеты nuget для .net 4.5.1 во всех трех сборках. По какой-то причине, хотя nuget ссылки не показывались в сборке "B", она успешно строилась.

оказалось, что реальная проблема заключалась в том, что сборки ссылались на разные версии пакета nuget, который содержал интерфейс, и подпись интерфейса изменилась между версиями.


в моем случае я ранее ссылался на mylib проект в папке sibling вне РЕПО-назовем это v1.0.

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

позже я сделал это правильно и использовал его через подмодуль git-давайте назовем это v2.0. Один проект consoleApp однако не был обновлен должным образом. Он все еще ссылался на старое v1.0 проект вне моего проекта git.

знаки, хотя *.csproj было явно неправильно и указывая на v1.0, среда IDE Visual Studio показала путь как ! F12 для проверки интерфейса и класса пошел в v2.0 версия тоже.

сборка, помещенная компилятором в папку bin, была v1.0 версия, отсюда и головная боль.

тот факт, что IDE лгал мне, сделал его очень трудным для понимания ошибки.

решение: удалены ссылки на проект из ConsoleApp и readded их.

Общий Совет: перекомпилировать все сборки с нуля (где это возможно, не может для пакетов nuget, конечно) и проверить метки datetime в . Любые старые устаревшие сборки-ваша проблема.


Я столкнулся почти с той же проблемой. Я чесал голову, что вызывает эту ошибку. Я перекрестно проверил, все методы были реализованы.

на Googling я получил эту ссылку среди других. Основываясь на комментарии @Paul McLink, эти два шага решили проблему.

  1. Перезапустите Visual Studio
  2. Очистить, Построить (Восстановить)

и ошибка ушла.

перезапустить VS плагин

Спасибо Павел :)

надеюсь, это поможет кому-то, кто столкнется с этой ошибкой :)


Я также столкнулся с этой проблемой при запуске моих unittests. Приложение работало нормально и без ошибок. Причиной проблемы в моем случае было то, что я отключил построение тестовых проектов. Восстановление здания моих testprojects решило проблемы.


Я видел это в Visual Studio Pro 2008, когда два проекта построили сборки с тем же именем, один класс lib SDF.dll и тот, который ссылается на lib с именем сборки sdf.исполняемый. Когда я изменил имя ссылочной сборки, исключение исчезло


- Это моя ошибка.

добавил extern метод, но моя паста была неисправна. The DllImportAttribute был поставлен на прокомментированную линию.

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

обеспечение того, что атрибут был фактически включен в источник, исправило проблему.


Я получил это в службе WCF из-за того, что был выбран тип сборки x86, в результате чего bisn жил под bin\x86 вместо bin. Выбор любого процессора заставил перекомпилированные библиотеки DLL перейти в правильные места (я не буду вдаваться в подробности о том, как это произошло в первую очередь).


Это просто означает, что проект реализации устарел в моих случаях. DLL, содержащая интерфейс, была перестроена, но dll реализации была устаревшей.


У меня была та же проблема. Я выяснил, что моя сборка, которая загружается основной программой, имеет некоторые ссылки с "Copy Local", установленным в true. Эти локальные копии ссылок искали другие ссылки в той же папке, которая не существовала, потому что "копировать локальные" другие ссылки было установлено значение false. После удаления "случайно" скопированных ссылок ошибка исчезла, потому что основная программа была настроена на поиск правильных местоположений ссылок. Видимо локальные копии ссылок испортили последовательность вызова, потому что эти локальные копии использовались вместо оригинальных, присутствующих в основной программе.

сообщение take home заключается в том, что эта ошибка появляется из-за отсутствия ссылки для загрузки требуемой сборки.


в моем случае, я пытался использовать TypeBuilder создать тип. TypeBuilder.CreateType бросил это исключение. В конце концов я понял, что мне нужно добавить MethodAttributes.Virtual к атрибутам при вызове TypeBuilder.DefineMethod для метода, который помогает реализовать интерфейс. Это связано с тем, что без этого флага метод не реализует интерфейс, а вместо этого новый метод с той же сигнатурой (даже без указания MethodAttributes.NewSlot).


в качестве добавления: это также может произойти, если вы обновите пакет nuget, который использовался для создания сборки fakes. Скажем, вы устанавливаете V1.0 пакета nuget и создайте сборку подделок " fakeLibrary.1.0.0.0.Подделки." Затем вы обновляете до последней версии пакета nuget, скажем v1.1, который добавил новый метод к интерфейсу. Библиотека подделок все еще ищет v1.0 библиотеки. Просто удалите фальшивую сборку и восстановите ее. Если это была проблема, это, вероятно, исправит ее.


Я получил эту ошибку после недавнего обновления Windows. У меня был класс обслуживания, установленный для наследования от интерфейса. Интерфейс содержал подпись, которая возвращала ValueTuple, довольно новую функцию в C#.

все, что я могу предположить, что Центр обновления windows установил новый, но даже явно ссылаясь на него, обновляя перенаправления привязки и т. д...Конечным результатом было просто изменение подписи метода на что-то" стандартное", Я думаю, вы могли бы сказать.