TypeLoadException говорит "нет реализации", но он реализован
У меня очень странная ошибка на нашей тестовой машине. Ошибка:
System.TypeLoadException: Method 'SetShort' in type 'DummyItem' from assembly 'ActiveViewers (...)' does not have an implementation.
Я просто не понимаю, почему. SetShort
существует в классе DummyItem
, и я даже перекомпилировал версию с записью в журнал событий, чтобы убедиться, что это не проблема с развертыванием/версией. Странно то, что вызывающий код даже не вызывает метод SetShort
.
Ответы
Ответ 1
ПРИМЕЧАНИЕ. Если этот ответ вам не поможет, найдите время, чтобы просмотреть другие ответы, которые люди добавили с тех пор.
Короткий ответ
Это может произойти, если вы добавите метод к интерфейсу в одной сборке, а затем к классу реализации в другой сборке, но вы перестраиваете сборку, не ссылаясь на новую версию сборки интерфейса.
В этом случае DummyItem реализует интерфейс из другой сборки. Недавно был добавлен метод SetShort как для интерфейса, так и для DummyItem, но сборка, содержащая DummyItem, была восстановлена, ссылаясь на предыдущую версию сборки интерфейса. Таким образом, метод SetShort эффективно существует, но без волшебного соуса, связывающего его с эквивалентным методом в интерфейсе.
Длинный ответ
Если вы хотите попробовать воспроизвести это, попробуйте следующее:
-
Создайте проект библиотеки классов: InterfaceDef, добавьте только один класс и создайте:
public interface IInterface
{
string GetString(string key);
//short GetShort(string key);
}
-
Создайте проект библиотеки второго класса: Реализация (с отдельным решением), скопируйте 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
}
-
Создайте третий проект консоли: ClientCode, скопируйте две библиотеки dll в каталог проекта, добавьте ссылки на файлы и добавьте следующий код в метод Main:
IInterface test = new ImplementingClass();
string s = test.GetString("dummykey");
Console.WriteLine(s);
Console.ReadKey();
-
Запустите код один раз, консоль говорит "привет мир"
-
Раскомментируйте код в двух проектах dll и перестройте - скопируйте две dll обратно в проект ClientCode, перестройте и повторите попытку. TypeLoadException возникает при попытке создать экземпляр класса ImplementingClass.
Ответ 2
В дополнение к тому, что уже было сказано самим респондентом, возможно, стоит отметить следующее. Причина этого в том, что класс может иметь метод с той же сигнатурой, что и метод интерфейса, без реализации этого метода. Следующий код иллюстрирует, что:
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
Ответ 3
Я получил это, когда в моем приложении не было ссылки на другую сборку, определяющую класс, который используется в методе в сообщении об ошибке. Запуск PEVerify дал более полезную ошибку: "Система не может найти указанный файл".
Ответ 4
Я наткнулся на одно сообщение, и вот что мы нашли:
Мы используем сторонние DLL в нашем проекте. После выхода новой версии мы изменили наш проект, чтобы указать на новый набор dll и скомпилировать его успешно.
Исключение было брошено, когда я пытался установить один из своих сопряженных классов во время выполнения.
Мы следили за тем, чтобы все остальные ссылки были в курсе событий, но до сих пор не повезло.
Нам понадобилось некоторое время, чтобы обнаружить (используя "Обозреватель объектов" ), что возвращаемый тип метода в сообщении об ошибке был совершенно новым типом из новой сборки без ссылок.
Мы добавили ссылку на сборку, и ошибка исчезла.
- Сообщение об ошибке было довольно вводящим в заблуждение, но указало более или менее на правильное направление (правый метод, неправильное сообщение).
- Исключение возникло, хотя мы не использовали данный метод.
- Что приводит меня к вопросу: если это исключение бросается в любом случае, почему компилятор не подбирает его?
Ответ 5
Я получил эту ошибку в следующем сценарии.
- Обе сборки A и B, на которые ссылается System.Web.Mvc Version 3.0.0.0
- Сборка Ссылка на сборку B и классы, которые реализовали интерфейсы из сборки B с помощью методов, которые возвращали классы из System.Web.Mvc.
- Сборка Обновлен до версии 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. Кажется очевидным сейчас!
Благодаря оригинальному плакату!
Ответ 6
В другой раз вы можете получить эту ошибку, если у вас есть некорректная версия подписанной сборки. Это не нормальный симптом по этой причине, но вот сценарий, где я получил его
-
Проект asp.net содержит сборку A и сборку B, B сильно назван
-
В сборке A используется Activator.CreateInstance для загрузки сборки C (т.е. нет ссылки на C, которая построена отдельно)
-
C была создана ссылка на более раннюю версию сборки B, чем в настоящее время
Надеюсь, что это поможет кому-то - мне потребовались годы, чтобы понять это.
Ответ 7
У меня тоже была эта ошибка, она была вызвана любым процессором exe, ссылающимся на любые сборки процессора, которые, в свою очередь, ссылались на сборку x86.
Исключение жаловалось на метод класса в MyApp.Implementations(Any CPU), который получил MyApp.Interfaces(любой процессор), но в fuslogvw.exe я обнаружил скрытую "попытку загрузить программу с неправильным форматом", исключение из MyApp.CommonTypes(x86), которое используется обоими.
Ответ 8
Я продолжаю возвращаться к этому...
Многие из ответов здесь дают большую работу по разъяснению проблемы, но не как ее исправить.
Решение этого - вручную удалить файлы bin в опубликованных каталогах проектов. Он очистит все ссылки и заставит проект использовать последние DLL.
Я не предлагаю использовать функцию публикации инструментов Delete, потому что это имеет тенденцию отбрасывать IIS.
Ответ 9
У меня есть еще одно эзотерическое решение для этого сообщения об ошибке. Я обновил свою целевую структуру с .Net 4.0 до 4.6, а проект unit test дал мне ошибку "Ошибка System.TypeLoadException... не имеет реализации" при попытке создания. Он также дал второе сообщение об ошибке о том же якобы не реализованном методе, в котором говорилось, что задача "BuildShadowTask" неожиданно завершилась ". Ни один из рекомендаций здесь не помог, поэтому я искал "BuildShadowTask" и нашел сообщение в MSDN, что привело меня к использованию текстового редактора для удаления этих строк из файла csproj проекта unit test.
<ItemGroup>
<Shadow Include="Test References\MyProject.accessor" />
</ItemGroup>
После этого обе ошибки ушли и проект был построен.
Ответ 10
Я столкнулся с этой ошибкой в контексте, где я использовал 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 VM, 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>
Ответ 11
Я получил это с зависимостью от "алмазной" формы:
- В проекте A используется проект B и проект D
- В проекте B используется Project D
Я перекомпилировал проект A, но не проект B, который позволил проекту B "ввести" старую версию DLL Project D
Ответ 12
Я столкнулся с этим, когда переименовал проект (и имя сборки), от которого зависел проект ASP.NET. Типы в веб-проекте реализовали интерфейсы в зависимой сборке. Несмотря на выполнение Clean Solution из меню Build, сборка с предыдущим именем осталась в папке bin
, а когда мой веб-проект выполнен
var types = AppDomain.CurrentDomain.
GetAssemblies().
ToList().
SelectMany( s => s.GetTypes() /* exception thrown in this call */ )
;
указанное выше исключение было брошено, жалуясь на то, что методы интерфейса в реализующих веб-типах фактически не выполнялись. В ручном удалении сборки в веб-проекте папка bin
устранена проблема.
Ответ 13
Я также получил эту ошибку, когда ранее я включил Code Coverage во время модульного тестирования для одной из сборок. По какой-то причине Visual Studio "забуферировала" старую версию этой конкретной DLL, хотя я обновил ее для реализации новой версии интерфейса. Отключение кода покрытия избавилось от ошибки.
Ответ 14
FWIW, я получил это, когда был файл конфигурации, перенаправленный на несуществующую версию ссылочной сборки. Fusion logs для победы!
Ответ 15
Другое объяснение этой проблемы с управляемым С++.
Если вы попытаетесь заглушить интерфейс, определенный в сборке, созданной с помощью управляемого С++, которая имеет специальную подпись, вы получите исключение при создании заглушки.
Это верно для 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)
Обратите внимание, что тип С++ long
отображается в System.Int32
(или просто int
в С#). Это несколько неясное modopt
, вызывающее проблему как указано Ayende Rahien в списке рассылки Rhino Mocks.
Ответ 16
Эта ошибка также может быть вызвана, если сборка загружается с помощью Assembly.LoadFrom(String) и ссылается на сборку, которая уже была загружена с помощью Assembly.Load(Byte []).
Например, вы ввели основные ссылки, связанные с приложениями, в качестве ресурсов, но ваше приложение загружает плагины из определенной папки.
Вместо использования 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;
}
Ответ 17
Я только что обновил решение от MVC3 до MVC5 и начал получать то же исключение из моего проекта Unit test.
Проверено все ссылки на старые файлы, в конце концов я обнаружил, что мне нужно сделать некоторые bindRedirects для Mvc в моем проекте Unit test.
<?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>
Ответ 18
В моем случае это помогло reset панели инструментов WinForms.
Я получил исключение при открытии Form
в дизайнере; однако компиляция и запуск кода были возможны, и код вел себя так, как ожидалось. Исключение произошло в локальном UserControl
, реализующем интерфейс из одной из моих ссылочных библиотек. Ошибка появилась после обновления этой библиотеки.
Этот UserControl
был указан в панели инструментов WinForms. Вероятно, Visual Studio сохранила ссылку на устаревшую версию библиотеки или где-то кэшировала устаревшую версию.
Вот как я оправился от этой ситуации:
- Щелкните правой кнопкой мыши на панели инструментов WinForms и выберите
Reset Toolbox
в контекстном меню. (Это удаляет пользовательские элементы из панели инструментов).
В моем случае элементы Toolbox были восстановлены до состояния по умолчанию; однако стрелка указателя отсутствовала в панели инструментов.
- Закрыть Visual Studio.
В моем случае Visual Studio закончила с нарушением исключения и прервалась.
- Перезапустить Visual Studio.
Теперь все работает гладко.
Ответ 19
Я получил эту ошибку, потому что у меня был класс в сборке "C", которая была на версии 4.5 фреймворка, реализовав интерфейс в сборке "A", который был на версии 4.5.1 структуры и служил базой класса к сборке "B" , которая также была включена в версию 4.5.1. При попытке загрузить сборку "B" система исключила исключение. Кроме того, я установил некоторые пакеты nuget, нацеленные на .net 4.5.1 для всех трех сборок. По какой-то причине, хотя ссылки на nuget не показывались в сборке "B" , она успешно строилась.
Оказалось, что настоящая проблема заключалась в том, что сборки ссылались на разные версии пакета nuget, которые содержали интерфейс, а подпись интерфейса была изменена между версиями.
Ответ 20
В моем случае я ранее ссылался на проект mylib
в папке сиблинга вне репо - позвонил, v1.0
.
|-- myrepo
| |-- consoleApp
| |-- submodules
| |-- mylib (submoduled v2.0)
|-- mylib (stale v1.0)
Позже я сделал это правильно и использовал его через подмодуль git - позволяет называть это v2.0
.
Однако один проект consoleApp
не был обновлен должным образом. Он по-прежнему ссылался на старый проект v1.0
за пределами моего проекта git.
Confusingly, хотя *.csproj
был явно неправильным и указывал на v1.0
, IDE Visual Studio показал путь как проект v2.0
!
F12 для проверки интерфейса и класса также отправился в версию v2.0
.
Установкой, помещенной в папку bin компилятором, была версия v1.0
, следовательно, головная боль.
Тот факт, что IDE лгал мне, затруднял реализацию ошибки.
Решение: Удаленные ссылки на проект из consoleApp
и их чтение.
Общий совет: Скомпилируйте все сборки с нуля (где это возможно, не обязательно для пакетов nuget, конечно) и проверьте штампы datetime в папке bin\debug
. Любая старая встреча в сборе - ваша проблема.
Ответ 21
Я столкнулся с почти той же проблемой. Я почесал голову, что вызывает эту ошибку.
Я перекрестился, все методы были реализованы.
В Googling я получил эту ссылку среди других. Основываясь на комментарии @Paul McLink, эти два шага решили проблему.
- Перезапустить Visual Studio
- Очистить, скомпилировать (перестроить)
и ошибка.
Перезапустить VS-плагин
Спасибо, Пол:)
Надеюсь, что это поможет кому-то, кто сталкивается с этой ошибкой:)
Ответ 22
Я получил это в службе WCF из-за того, что был выбран тип сборки x86, в результате чего бины находились в bin\x86 вместо bin. Выбор любого ЦП привел к тому, что перекомпилированные библиотеки DLL оказались в правильных местах (я не буду вдаваться в подробности того, как это произошло в первую очередь).
Ответ 23
Я также столкнулся с этой проблемой во время запуска моих unittests. Приложение работает нормально и без ошибок.
Причиной проблемы в моем случае было то, что я отключил здание тестовых проектов.
Реконструкция здания моих тестовых проектов решила проблемы.
Ответ 24
Я видел это в Visual Studio Pro 2008, когда два проекта строили сборки с тем же именем, один из классов lib SDF.dll и тот, который ссылался на lib с именем сборки sdf.exe.
Когда я изменил имя сборки ссылок, исключение исчезло
Ответ 25
Здесь я беру на себя эту ошибку.
Добавлен метод extern
, но моя паста была ошибочной. DllImportAttribute
попал в пропущенную строку.
/// <returns>(removed for brevity lol)</returns>[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindowVisible(IntPtr hWnd);
Обеспечение того, что атрибут был включен в исходный код, исправил проблему.
Ответ 26
Это просто означает, что проект реализации устарел в моих случаях. DLL, содержащая интерфейс, была перестроена, но DLL реализации была устаревшей.
Ответ 27
У меня была та же проблема. Я понял, что моя сборка, загружаемая основной программой, имела некоторые ссылки с "Копировать локальную" в true. Эти локальные копии ссылок искали другие ссылки в той же папке, которых не было, потому что для "Копировать локальную" других ссылок было установлено значение false. После удаления "случайно" скопированных ссылок ошибка исчезла, потому что основная программа была настроена на поиск правильных мест ссылок. По-видимому, локальные копии ссылок привили последовательность вызовов, потому что эти локальные копии использовались вместо исходных, присутствующих в основной программе.
Принять домашнее сообщение о том, что эта ошибка появляется из-за отсутствия ссылки для загрузки необходимой сборки.
Ответ 28
В моем случае я пытался использовать TypeBuilder
для создания типа. TypeBuilder.CreateType
выбрал это исключение. В конце концов я понял, что мне нужно добавить MethodAttributes.Virtual
к атрибутам при вызове TypeBuilder.DefineMethod
для метода, который помогает реализовать интерфейс. Это связано с тем, что без этого флага метод не реализует интерфейс, а скорее новый метод с той же сигнатурой (даже без указания MethodAttributes.NewSlot
).
Ответ 29
В качестве дополнения: это также может произойти, если вы обновите пакет nuget, который использовался для создания сборки подделок. Скажем, вы устанавливаете V1.0 пакета nuget и создаете сборку подделок "fakeLibrary.1.0.0.0.Fakes". Затем вы обновляете самую новую версию пакета nuget, скажем, v1.1, которая добавила новый метод в интерфейс. Библиотека Fakes все еще ищет v1.0 библиотеки. Просто удалите поддельную сборку и регенерируйте ее. Если это проблема, возможно, это исправить.
Ответ 30
Я получил эту ошибку после недавнего обновления Windows. У меня был класс сервисов, наследуемый от интерфейса. Интерфейс содержит подпись, которая вернула ValueTuple, довольно новую функцию на С#.
Все, что я могу догадаться, это то, что обновление Windows установило новый, но даже явно ссылалось на него, обновляя переадресацию связывания и т.д. Конечным результатом было просто изменение сигнатуры метода на что-то "стандартное". Я полагаю, вы может сказать.