与PCL一起使用TypeNameAssemblyFormat时,Newtonsoft.Json缺少MissingMethodException [英] MissingMethodException with Newtonsoft.Json when using TypeNameAssemblyFormat with PCLs

查看:310
本文介绍了与PCL一起使用TypeNameAssemblyFormat时,Newtonsoft.Json缺少MissingMethodException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将TypeNameAssemblyFormat与PCL一起使用是否存在问题?使用Newtonsoft.Json进行任何其他设置都没有问题,除非使用此序列化设置.

这是我与Json相关的代码:

var settings = new JsonSerializerSettings()
        {
            TypeNameHandling = TypeNameHandling.Objects,
            Formatting = Formatting.Indented,
            TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full
        };

var json = JsonConvert.SerializeObject(obj, settings);

var jsonBytes = Encoding.UTF8.GetBytes(json);

return jsonBytes;

当我在声明它的同一个库中进行调用时,就可以了.但是,当我从另一个调用上述代码的PCL进行调用时,我得到了缺少的方法异常.仅当我使用TypeNameAssemblyFormat设置时才会发生这种情况(即,如果我不必使用该设置,那么我就不会写这篇文章了;).

我正在使用PCL配置文件7.

异常(我不想否认整个堆栈跟踪,但是如果有人认为有帮助的话,我可以):

"System.MissingMethodException: Method not found: 'Void Newtonsoft.Json.JsonSerializerSettings.set_TypeNameAssemblyFormat(System.Runtime.Serialization.Formatters.FormatterAssemblyStyle)'

解决方案

尽管问题中没有足够的信息以100%的置信度确认根本原因.唯一的合理 解释如下-

简而言之-在失败的测试中,Newtonsoft.Json.dll的正确(便携式)版本没有未加载.

详细-正在执行两项测试.

  1. 通过-我假设有一个exe,可以调用PCL1,它可以调用便携式版本的NewtonSoft.Json.dll

  2. 失败-我假设 另一个 exe,它会调用PCL2,后者会调用PCL1,后者会版本( 版本? )的NewtonSoft.Json.dll

问题不是不是,因为 间接 被调用为NewtonSoft.Json.dll,因此PCL2调用了PCL1并以某种方式失败.相反,问题是,正如我在上面试图强调的那样, 第二 测试恰好以某种方式设置,即错误/不可移植版本的NewtonSoft.Json.dll供PCL1使用.

在失败的情况下,请想象该应用程序的exe或任何其他非便携式程序集也依赖于NewtonSoft.Json.dll的(非便携式)版本.在这种情况下,在应用程序/exe的输出文件夹中,将只有一个NewtonSoft.Json.dll版本,如果它是非便携式版本,则它将失败,并出现上述异常..

进一步的解释-为什么?

System.Runtime.Serialization.Formatters.FormatterAssemblyStyle类型通常在mscorlib.dll中定义.但是,此类型不适用于可移植类库(不了解所有配置文件,但是可以肯定有一些配置文件,这些配置文件不可用).因此,NewtonSoft.Json.dll便携式版本 在它自己的程序集中声明了它本身 .

在您喜欢的反编译器中检查便携式 NewtonSoft.Json.dll的反编译版本. 请注意下面的第3行..摘录中的摘录来自NewtonSoft.Json.dll.

// Decompiled with JetBrains decompiler
// Type: System.Runtime.Serialization.Formatters.FormatterAssemblyStyle
// Assembly: Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
// Assembly location: C:\Users\.....\packages\Newtonsoft.Json.6.0.7\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll
// Compiler-generated code is shown

namespace System.Runtime.Serialization.Formatters
{
  /// <summary>
  /// Indicates the method that will be used during deserialization for locating and loading assemblies.
  /// 
  /// </summary>
  public enum FormatterAssemblyStyle
  {
    Simple,
    Full,
  }
}

现在,当您在引用TypeNameAssemblyFormat属性的PCL中编译代码时,将生成以下IL(使用Ildasm反编译),该属性假定类型为System.Runtime.Serialization.Formatters.FormatterAssemblyStyle Newtonsoft.Json.dll中定义. -

  IL_0017:  ldloc.0
  IL_0018:  ldc.i4.1
  IL_0019:  callvirt   instance void [Newtonsoft.Json]Newtonsoft.Json.JsonSerializerSettings::set_TypeNameAssemblyFormat(valuetype [Newtonsoft.Json]System.Runtime.Serialization.Formatters.FormatterAssemblyStyle)

请注意如何使用程序集名称[Newtonsoft.Json]来限定对类型的引用(滚动到右侧的-----> 可以在传递的FormatterAssemblyStyle参数上查看它).

现在,如果将此便携式版本的Newtonsoft.Json.dll替换为非便携式版本(因为项目的其他部分引用了非便携式版本),则在运行时,CLR将无法找到与上述版本匹配的方法签名(,如上面的IL中看到的).因此失败,并显示System.MissingMethodException.

不幸的是,异常本身无法提供有关所要查找方法的完整和确切签名的足够信息,包括程序集名称.仅类型名称就具有欺骗性 strong>看起来可能会存在于系统dll之一(在本例中为mscorlib.dll)中.而不是Newtonsoft.json.dll的可移植版本.

Is there a problem with using the TypeNameAssemblyFormat with PCLs? I have no problems using any other settings with Newtonsoft.Json except when I use this serialization setting.

Here is my Json-related code:

var settings = new JsonSerializerSettings()
        {
            TypeNameHandling = TypeNameHandling.Objects,
            Formatting = Formatting.Indented,
            TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full
        };

var json = JsonConvert.SerializeObject(obj, settings);

var jsonBytes = Encoding.UTF8.GetBytes(json);

return jsonBytes;

When I make the call within the same library where it is declared, it is fine. However, when I make the call from a different PCL that calls the above code, I get the missing method exception. This only occurs when I use the TypeNameAssemblyFormat setting (i.e. if I didn't have to use that setting then I wouldn't be writing this post ;).

I am using PCL profile 7.

Exception (I didn't want to blah the entire stack trace, but I can if anyone thinks that would help):

"System.MissingMethodException: Method not found: 'Void Newtonsoft.Json.JsonSerializerSettings.set_TypeNameAssemblyFormat(System.Runtime.Serialization.Formatters.FormatterAssemblyStyle)'

解决方案

Although there isn't enough information in the question to confirm the root cause with 100% confidence.. Personally, after some experimentation I am positive that the only plausible explanation is as follows -

In short - In the test which fails, the correct (portable) version of Newtonsoft.Json.dll is not getting loaded.

In long - There are two tests being performed.

  1. Passes - I presume an exe, which calls into PCL1, which calls into portable version of NewtonSoft.Json.dll

  2. Fails - I presume another exe, which calls into PCL2, which calls into PCL1, which calls into a version (which version?) of NewtonSoft.Json.dll

The issue is not that PCL2 calls into PCL1 and somehow fails, due to indirect call being made into NewtonSoft.Json.dll. Rather, the issue is, as I am trying to highlight above, the second test happens to be setup in a way, that the wrong / non-portable version of NewtonSoft.Json.dll is available for PCL1 to consume.

In scenario which fails, imagine that the exe or any other non-portable assembly of that application also takes a dependency on (non-portable) version of NewtonSoft.Json.dll. In that case, in the output folder of the application / exe, there will be only one version of NewtonSoft.Json.dll, and if it is the non-portable one, then it will fail with above mentioned exception..

Further explanation - Why?

The type System.Runtime.Serialization.Formatters.FormatterAssemblyStyle is typically defined in mscorlib.dll. However, this type is not available for Portable class libraries to use (don't know about all profiles, but there are some profiles for sure, which do not have this type available). Hence the portable version of NewtonSoft.Json.dll, declares it itself, in it's own assembly.

Check the decompiled version of portable NewtonSoft.Json.dll in your favorite decompiler. Note line number 3 below.. following snippet is from NewtonSoft.Json.dll.

// Decompiled with JetBrains decompiler
// Type: System.Runtime.Serialization.Formatters.FormatterAssemblyStyle
// Assembly: Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
// Assembly location: C:\Users\.....\packages\Newtonsoft.Json.6.0.7\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll
// Compiler-generated code is shown

namespace System.Runtime.Serialization.Formatters
{
  /// <summary>
  /// Indicates the method that will be used during deserialization for locating and loading assemblies.
  /// 
  /// </summary>
  public enum FormatterAssemblyStyle
  {
    Simple,
    Full,
  }
}

Now, when you compile code in a PCL, which references TypeNameAssemblyFormat property, presumeable of type System.Runtime.Serialization.Formatters.FormatterAssemblyStyle defined in Newtonsoft.Json.dll, following IL is generated (decompiled using Ildasm) -

  IL_0017:  ldloc.0
  IL_0018:  ldc.i4.1
  IL_0019:  callvirt   instance void [Newtonsoft.Json]Newtonsoft.Json.JsonSerializerSettings::set_TypeNameAssemblyFormat(valuetype [Newtonsoft.Json]System.Runtime.Serialization.Formatters.FormatterAssemblyStyle)

Note how reference to the type is qualified with the assembly name [Newtonsoft.Json] (scroll to the right -----> to see it on the FormatterAssemblyStyle parameter being passed).

Now, if this portable version of Newtonsoft.Json.dll, gets replaced with non-portable version (because other parts of the project reference non-portable version), then at runtime, CLR will be unable to find method which matches the above signature (as seen in IL above).. and hence fail with System.MissingMethodException.

Unfortunately, the exception itself doesn't give enough information about the complete and exact signature of method it is looking for, including the assembly names.. The type name alone deceptively looks like something that would exist in one of the system dlls (mscorlib.dll in this case).. and not portable version of Newtonsoft.json.dll.

这篇关于与PCL一起使用TypeNameAssemblyFormat时,Newtonsoft.Json缺少MissingMethodException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆