Невозможно загрузить сборки для. Net Стандартная библиотека (System.Text. Json) - PullRequest
7 голосов
/ 27 февраля 2020

Я пишу. Net Стандартную библиотеку 2.0, которая будет использоваться двоичным модулем PowerShell. Библиотека будет в основном клиентом API с большим количеством классов для обработки ответов JSON. Прежде чем пытаться десериализовать строки, я подтвердил, что API предоставлял кодированную строку JSON без проблем.

Поскольку она была совместима с. Net Стандарт 2.0 при использовании Пакет NuGet, я подумал, что попробую переключиться на System.Text. Json, а не на NewtonSoft. Однако, похоже, у него нет версии определенных сборок, которая требуется для определенных платформ.

Моя среда:

Windows 10
PowerShell 5.1 Desktop
. Net Framework 4.8
PowerShell Core 6.2.2
do tnet версия 3.0.100

При PowerShell Desktop возникают следующие проблемы, когда он должен десериализовать все, что угодно:

PS dir:\> Import-Module '.\file.dll'
PS dir:\> [namespace.class]::TestMethod($string, $anotherString)  # Test method to return string
{"attribute":"value"}
PS dir:\> [namespace.class]::Method($string, $anotherString)  # Same as above, but uses System.Text.Json to deserialise
Could not load file or assembly 'System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The system
cannot find the file specified.

# System.Buffers.dll is with the System.Text.Json package, but seems to be the wrong version
PS dir:\> (Get-Item .\System.Buffers.dll).VersionInfo.FileVersion
4.6.26515.06
PS dir:\> [System.Reflection.Assembly]::LoadFile("$pwd\System.Buffers.dll").GetName().Version

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      3      0

На PowerShell Core там такое же исключение для другой сборки / файла.

PS dir:\> Import-Module '.\file.dll'
PS dir:\> [namespace.class]::Method($string, $anotherString)
"Could not load file or assembly 'System.Text.Encodings.Web, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. Could not find or load a specific file. (Exception from HRESULT: 0x80131621)"

#System.Text.Encodings.Web.dll is with the System.Text.Json package and appears to be the required version...
PS dir:\> (Get-Item .\System.Text.Encodings.Web.dll).VersionInfo.FileVersion
4.700.19.56404
[System.Reflection.Assembly]::LoadFile("$pwd\System.Text.Encodings.Web.dll").GetName().Version

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      5      0

Кто-нибудь получил какие-либо советы о том, как я можно решить эту проблему, не переходя на пакет Newtonsoft JSON? Откат от System.Text. Json 4.7.1 до 4.7.0 или 4.6.0 приводит к проблемам с другими сборками, которые являются частью пакета NuGet для System.Text. Json. Я прочитал совет здесь , но я либо не могу применить его здесь, либо я просто не понимаю.

Заранее спасибо. Пожалуйста, дайте мне знать, если вам потребуется дополнительная информация, я предоставлю ее.

РЕДАКТИРОВАТЬ

Я обновил csproj в соответствии с рекомендациями Гохана

<PropertyGroup>
  <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>

Это сгенерировало следующий код в appName.dll.config

<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

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

Ответы [ 3 ]

2 голосов
/ 10 марта 2020

Проблема, с которой вы сталкиваетесь, заключается в том, что ваша библиотека нацеливается. NET Стандарт, который не является работоспособной средой, поэтому иногда возникают проблемы при попытке загрузить его с использованием моделей, подобных модели Powershell. Позвольте мне попытаться объяснить немного больше, что происходит.

. NET Стандарт - это просто площадь поверхности API Spe c, так что в основном это просто набор API, которые будут гарантированно присутствовать и чтобы иметь возможность работать на любой работающей среде, которая реализует эту версию. NET Standard. Это означает, что если у вас есть библиотека, предназначенная для. NET Standard, то нет реального способа опубликовать sh эту библиотеку со всеми ее зависимостями таким образом, чтобы она гарантированно работала на любой работающей среде, потому что каждая работоспособная Framework может потребоваться дополнительные зависимости для вашей библиотеки для правильной загрузки. При ссылке на стандартную библиотеку. NET из консольного приложения (либо через ссылку на проект, либо через пакет NuGet) консольное приложение будет знать, на какую работоспособную среду он нацелен, поэтому оно сможет получить правильный набор зависимостей, которые ваша библиотека потребуется во время выполнения, но проблема с вашим сценарием в том, что это консольное приложение на самом деле не существует, так как вы загружаете его из powershell (который в некотором смысле является в основном консольным приложением). Из-за всего этого для успешной загрузки вашей библиотеки во время выполнения вам придется выполнить работу, которую будет выполнять консольное приложение, ссылающееся на вашу библиотеку, и выбрать правильные ссылки для переноса вашей библиотеки в зависимости от времени выполнения, которое будет загружаю это. Для powershell существует в основном две возможные среды выполнения (. NET Core для powershell core и. NET Framework для Powershell).

Самый простой способ решить вашу проблему, это просто создать одно фиктивное консольное приложение: из командной строки просто запустите dotnet new console -n dummyConsoleApp, установите targetframework на netcoreapp2.0 (если вы работаете на ядре powershell, если вы вместо этого на полную мощность PowerShell, а затем установите его net46). Затем добавьте ссылку на проект в вашу библиотеку, например <ProjectReference Include="...<FullPathtoYourProject>\File.csproj" />, и затем запустите из командной строки dotnet publish -r win-x64, которая должна создать в вашей папке bin каталог publi sh, который будет содержать все сборки, которые ваше приложение будет использовать во время выполнения. После этого попробуйте снова загрузить файл File.dll, но на этот раз из этой папки publi sh, и на этот раз вы добьетесь успеха, поскольку эта папка publi sh будет иметь все необходимые зависимости, необходимые для среды выполнения, которая PowerShell работает на. Если по какой-либо причине это не работает для вас, пожалуйста, не стесняйтесь регистрировать проблему об этом в https://github.com/dotnet/runtime репо и пометить меня (@joperezr), и я с радостью помогу вам диагностировать и исправить выпуск.

0 голосов
/ 04 марта 2020

Откройте ваше решение в Visual studio. Проверьте вашу ссылку на все библиотеки DLL. У вас есть дубликат dll один из бин, а другой из пакета самородок? Если у вас Visual Studio 2017 версии 15.7 или новее, вы можете легко отключить автоматически создаваемые перенаправления привязки на страницах свойств проекта.

Щелкните правой кнопкой мыши проект в обозревателе решений и выберите Свойства.

На вкладке На странице приложения снимите флажок Автоматически создавать перенаправления привязки.

Нажмите Ctrl + S, чтобы сохранить изменения. Попробуйте построить это. Проверьте, что вы ссылаетесь на все Dll из местоположения слепка, а ничего нет из папки bin. Если это сборка, вы хороши для go, в противном случае выполните связывание с перенаправлением компиляции снова.

0 голосов
/ 27 февраля 2020

Если вы не можете найти причину конфликта версий для System.Buffers DLL, я думаю, вы можете использовать assemblybinding в вашем конфигурационном файле, чтобы использовать версию 4.0.3.0 вместо 4.0.2.0

<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51"/>
        <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
      </dependentAssembly>
    </assemblyBinding>
 </runtime>

Если у вас есть другие конфликты версий, удалите все теги dependentassembly в файле конфигурации (включая приведенный выше) и добавьте их в файл проекта (.csproj):

<PropertyGroup>
  <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>

Когда вы создаете свой проекта, вы увидите файл (WebAppName) .dll.config в папке выходного бина. Скопируйте все assemblybindings оттуда в ваш исходный файл конфигурации. Затем удалите вышеуказанную часть кода из файла проекта.

...