简体   繁体   中英

System.Text.Json Deserialize Error System.MemoryExtensions Cannot Load System.Runtime.CompilerServices.Unsafe

Similar to another question , but with different symptoms and I didn't want to ask a question within a question.

Using VS2017 with all projects targeting .NET Framework 4.8. Tried oldest (4.6.0) and newest (5.0.2) versions of System.Text.Json. Also tried targeting all projects at .NET Framework 4.6.1. I built three projects:

  • MyClassLib - class library containing classes and code to built object instances from JSON returned from T-SQL queries

  • MyServiceLib - service library referencing and exposing certain functions within MyClassLib. Launched in Debug with typical WcfSvcHost.exe/WcfTestClient.exe treatment as MyService

  • MyTestClient - WinForms client referencing both MyClassLib and MyService (through Debug hosting of MyServiceLib) to test functionality. Reused objects in MyClassLib in referencing MyService

MyClassLib function performs perfectly when called from WinForms app, but gives the error below when called from service library. Specific line of code where it fails:

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

Inside MyClassLib, everything is exactly the same between the two call paths. What can be the difference?!?!

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

I notice the DLLs dragged along by System.Json.Text are a mix of 'Product name' Microsoft .NET Core and Microsoft .NET Framework:

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

Just noticed that the WinForms client runs as 32-bit while WcfSvcHost.exe runs as 64-bit.

Building a WinForms service host instead of using WcfSvcHost.exe was one approach to 'fixing' the problem. Part 1 of this answer suggested by @sean-skelly included a link to the System.Runtime.CompilerServices.Unsafe NuGet package . Playing with that has made me conclude you can't get the 4.0.4.1 version of the dll to coexist with 5.0.2 version of System.Text.Json. Smells like a Microsoft screw up. Moved everything to VS 2019 and used latest versions, but to no avail. Part 2 of answer suggested by @sean-skelly led to an article about bindingRedirect that seems somewhat helpful.

As several commenters noted, the error message stems from looking for one version of the dll but finding a different one. Ultimately, the answer is using bindingRedirect entries in one or another config file. I eventually took the projects into VS2019 on another machine and updated the NuGet package for System.Text.Json to the latest preview version (6.x). When it was working there, I copied the entire solution back to my machine running VS2017. It looks like that process resulted in some bindingRedirect entries being made in a couple of config files as indicated below. Still unanswered is why the original versions of MyClassLib.dll and MyServiceLib.dll using System.Text.Json 5.02 worked absolutely fine inside a WinForms client and service host, respectively, but MyServiceLib.dll hosted with WcfSvcHost.exe caused the error message in MyClassLib.dll. There were no bindingRedirect entries in any .config files and the System.Memory.dll and System.Runtime.CompilerServices.Unsafe.dll files were co-located with MyClassLib.dll, and of the exact same versions. But some things don't warrant further investigation as long as there is a workaround.

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM