TypeLoadException говорит «нет реализации», но оно реализовано - PullRequest
255 голосов
/ 04 июня 2009

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

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

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

Ответы [ 37 ]

231 голосов
/ 04 июня 2009

ПРИМЕЧАНИЕ - Если этот ответ вам не поможет, найдите время, чтобы прокрутить список других ответов, добавленных с тех пор.

Краткий ответ

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

В этом случае 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, скопируйте две библиотеки в каталог проекта, добавьте ссылки на файлы и добавьте следующий код в метод Main:

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

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

32 голосов
/ 08 июля 2009

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

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
22 голосов
/ 17 сентября 2009

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

19 голосов
/ 05 мая 2010

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

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

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

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

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

  • Обе сборки A и B ссылаются на System.Web.Mvc версии 3.0.0.0
  • Сборка A ссылалась на сборку B и имела классы, которые реализовывали интерфейсы из сборки B с методами, которые возвращали классы из System.Web.Mvc.
  • Сборка A обновлена ​​до System.Web.Mvc версии 4.0.0.0
  • Сборка C запустила приведенный ниже код (FertPin.Classes.Contact содержался в Сборке A):

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

Исправлением для меня было обновление ссылки System.Web.Mvc в сборке B до 4.0.0.0. Кажется очевидным сейчас!

Благодаря оригинальному постеру!

13 голосов
/ 30 ноября 2009

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

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

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

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

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

9 голосов
/ 18 августа 2010

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

Исключение жаловалось на метод класса в MyApp.Implementations (Any CPU), который получил MyApp.Interfaces (Any CPU), но в fuslogvw.exe я обнаружил скрытую «попытку загрузки программы с неверным форматом» исключение из MyApp.CommonTypes (x86), которое используется обоими.

6 голосов
/ 01 мая 2015

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

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

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

6 голосов
/ 14 ноября 2015

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

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

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

6 голосов
/ 23 марта 2017

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

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

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>
...