TypeLoadException Не удаётся загрузить тип

Встретился с такой проблемой.

Скомпилировал сборку под .NET 4.5. При попытке запуска на компьютере, где максимальная установленная версия .NET - 4.0, выпадает исключение TypeLoadException на тип в сборке System.Windows.Input. Разве не должна вылетать ошибка с несоответствием версии сборки и версии, установленной на ПК? Может быть я что то упускаю? При чём в сборку включено ещё 11 ссылок на библиотеки отсутсвующей версии .NET, но исключения кроме этого больше не выпадают. По идее же все сборки FCL имеют строгое имя и с каждой новой версией .NET - разное.


Ответы (1 шт):

Автор решения: MSDN.WhiteKnight

По идее же все сборки FCL имеют строгое имя и с каждой новой версией .NET - разное.

Только с каждой новой версией CLR, а не с каждым выпуском .NET. Т.е. 2.0-3.5 и 4.Х имеют разное строгое имя, а 4.0 и 4.5 - одинаковое.

Например, открываем сборку PresentationCore из .NET 4.8 в IL Disassembler, и видим такой фрагмент манифеста:

.assembly PresentationCore
{
  (...)

  .ver 4:0:0:0

  (...)
} 

Теперь откроем приложение, которое на нее ссылается, при целевой платформе .NET 4.5:

.assembly extern PresentationCore
{
  .ver 4:0:0:0
}

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

.custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) 
= ( 01 00 1A 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B   // ....NETFramework
    2C 56 65 72 73 69 6F 6E 3D 76 34 2E 35 01 00 54   // ,Version=v4.5..T
    0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C   // ..FrameworkDispl
    61 79 4E 61 6D 65 12 2E 4E 45 54 20 46 72 61 6D   // ayName..NET Fram
    65 77 6F 72 6B 20 34 2E 35 )                      // ework 4.5

Но он только для информации, при выполнении он ни на что не влияет (значение целевой платформы при проверке берется из app.config)

Также и реальную версию установленной сборки можно узнать из свойств файла

file properties

(C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationCore.dll)

Опять же, это значение ни на что не влияет. Оно хранится в Win32-ресурсе VERSION, а не в манифесте сборки.

Тут неизбежно возникает вопрос, как вообще работает понятие "целевая платформа", если версия везде одинаковая? Суть в следующем - когда вы выбираете целевую платформу, вы этим выбираете набор reference assemblies, соответствующий определенному выпуску .NET. Он содержит набор API, которые присутствуют в этом выпуске, и только их. Таким образом, если вы захотите использовать API, который появился в более новой версии, это не скомпилируется, и даже в IntelliSense вы его не увидите.

Скомпилировал сборку под .NET 4.5. При попытке запуска на компьютере, где максимальная установленная версия .NET - 4.0 выпадает исключение TypeLoadException

В этом случае приложение запустилось только потому, что вы удалили стандартный app.config, который указывает целевую платформу. Если бы он был, загрузчик бы вывел нормальное сообщение "Установите .NET Framework 4.5".

→ Ссылка