System.Text.Json 反序列化错误 System.MemoryExtensions 无法加载 System.Runtime.CompilerServices.Unsafe

问题描述

类似于another question,但症状不同,我不想在问题中提出问题。

在所有面向 .NET Framework 4.8 的项目中使用 VS2017。尝试了最旧 (4.6.0) 和最新 (5.0.2) 版本的 System.Text.Json。还尝试针对 .NET Framework 4.6.1 上的所有项目。我构建了三个项目:

  • MyClassLib - 包含要构建的类和代码的类库 从 T-SQL 查询返回的 JSON 对象实例

  • MyServiceLib - 服务库引用和公开某些 MyClassLib 中的函数。在调试中启动,典型的 WcfSvcHost.exe/WcfTestClient.exe 处理为 MyService

  • MyTestClient - WinForms 客户端同时引用 MyClassLib 和 MyService(通过 MyServiceLib 的调试托管)来测试功能。在引用 MyService 时重用 MyClassLib 中的对象

MyClassLib 函数在从 WinForms 应用程序调用时表现完美,但在从服务库调用时出现以下错误。失败的特定代码行:

Empl[] empls = JsonSerializer.Deserialize<Empl[]>(jsonString);

在 MyClassLib 中,两个调用路径之间的一切完全相同。有什么区别?!?!

System.TypeInitializationException: The type initializer for 'System.Text.Json.JsonSerializer' threw an exception. ---> System.TypeInitializationException:   The type initializer for 'System.MemoryExtensions' threw an exception. ---> System.IO.FileLoadException:
      Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe,Version=4.0.4.1,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a' or one of its
              dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)    at System.MemoryExtensions.MeasureStringAdjustment()    at System.MemoryExtensions..cctor()    --- End of inner exception stack trace ---    at System.MemoryExtensions.AsSpan(String text)    at System.Text.Json.JsonEncodedText.Encode(String value,JavaScriptEncoder encoder)    at System.Text.Json.JsonSerializer..cctor()    --- End of inner exception stack trace ---    at System.Text.Json.JsonSerializer.Deserialize[TValue](String json,JsonSerializerOptions options)    at GlobAppSecLib.GlobAppSec.RetEmplSecurity(String EmplNetworkID,String AppName) in C:\\[blah]\\MyClassLibModule.cs:line 155

System.TypeInitializationException: The type initializer for 'System.Text.Json.JsonSerializer' threw an exception. ---> System.TypeInitializationException:   The type initializer for 'System.MemoryExtensions' threw an exception. ---> System.IO.FileLoadException:
      Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe,String AppName) in C:\\[blah]\\MyClassLibModule.cs:line 155

我注意到 System.Json.Text 拖动的 DLL 是“产品名称”Microsoft .NET Core 和 Microsoft .NET Framework 的混合:

  • System.Text.Json.dll = Microsoft .NET Core
  • System.Memory.dll = Microsoft .NET Framework
  • System.Runtime.CompilerServices.Unsafe.dll = Microsoft .NET Framework

刚刚注意到 WinForms 客户端以 32 位运行,而 WcfSvcHost.exe 以 64 位运行。

构建 WinForms 服务主机而不是使用 WcfSvcHost.exe 是“修复”问题的一种方法。 @sean-skelly 建议的 this answer 的第 1 部分包含指向 the System.Runtime.CompilerServices.Unsafe NuGet package 的链接。玩这个让我得出结论,你不能让 4.0.4.1 版本的 dll 与 5.0.2 版本的 System.Text.Json 共存。闻起来像微软搞砸了。将所有内容移至 VS 2019 并使用最新版本,但无济于事。 @sean-skelly 建议的答案的第 2 部分导致 an article about bindingRedirect 似乎有些帮助。

解决方法

正如一些评论者所指出的,错误消息源于寻找一个版本的 dll 但找到了不同的版本。最终,答案是在一个或另一个配置文件中使用 bindingRedirect 条目。我最终将项目带到另一台机器上的 VS2019 中,并将 System.Text.Json 的 NuGet 包更新到最新的预览版本(6.x)。当它在那里工作时,我将整个解决方案复制回运行 VS2017 的机器。看起来该过程导致在几个配置文件中创建了一些 bindingRedirect 条目,如下所示。仍然未解决的问题是为什么使用 System.Text.Json 5.02 的 MyClassLib.dll 和 MyServiceLib.dll 的原始版本分别在 WinForms 客户端和服务主机中工作得非常好,但使用 WcfSvcHost.exe 托管的 MyServiceLib.dll 导致 MyClassLib 中出现错误消息.dll。任何 .config 文件中都没有 bindingRedirect 条目,并且 System.Memory.dll 和 System.Runtime.CompilerServices.Unsafe.dll 文件与 MyClassLib.dll 位于同一位置,并且版本完全相同。但只要有解决方法,有些事情就不需要进一步调查。

MyClassLib.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-6.0.0.0" newVersion="6.0.0.0" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>

MyServiceLib.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-6.0.0.0" newVersion="6.0.0.0" />
    </dependentAssembly>
    <dependentAssembly>
    <assemblyIdentity name="System.Text.Encodings.Web" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-5.0.0.1" newVersion="5.0.0.1" />
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...