尽管问题中没有足够的信息来以 100% 的置信度确认根本原因.. 就我个人而言,经过一些实验后,我是积极认为唯一似是而非的解释如下——
In short- 在失败的测试中,正确的(portable) 的版本Newtonsoft.Json.dll
is not正在加载。
In long- 正在进行两项测试。
通过 - 我假设有一个 exe,它调用 PCL1,它调用portable的版本NewtonSoft.Json.dll
失败——我认为anotherexe,它调用 PCL2,PCL2 调用 PCL1,PCL1 调用版本 (哪个版本?) of NewtonSoft.Json.dll
问题是notPCL2 调用 PCL1 并因某种原因失败indirect正在拨打电话NewtonSoft.Json.dll
。相反,正如我在上面试图强调的那样,问题是second测试恰好以某种方式设置,即错误/不可移植的版本NewtonSoft.Json.dll
可供 PCL1 使用。
在失败的情况下,想象一下该应用程序的 exe 或任何其他不可移植程序集也依赖于 (非便携式) 的版本NewtonSoft.Json.dll
。在这种情况下,在应用程序/exe的输出文件夹中,将只有一个版本NewtonSoft.Json.dll
,如果是非便携式一,那么它将因上述异常而失败..
进一步解释 - 为什么?
方式System.Runtime.Serialization.Formatters.FormatterAssemblyStyle
通常定义为mscorlib.dll
。但是,此类型不适用于可移植类库使用(不知道所有配置文件,但肯定有一些配置文件没有此类型可用)。因此portable的版本NewtonSoft.Json.dll
, 在它自己的程序集中声明它自己.
检查反编译版本portable 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,
}
}
现在,当您在 PCL 中编译代码时,它引用TypeNameAssemblyFormat
属性,推测类型System.Runtime.Serialization.Formatters.FormatterAssemblyStyle
定义于 Newtonsoft.Json.dll
,生成以下IL(使用反编译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)
请注意如何使用程序集名称来限定对类型的引用[Newtonsoft.Json]
(向右滚动----->看到它在FormatterAssemblyStyle
传递的参数)。
现在,如果这个便携式版本Newtonsoft.Json.dll
,被替换为不可移植版本(因为项目的其他部分引用了不可移植版本),那么在运行时,CLR将无法找到与上述签名匹配的方法(如上面的 IL 所示)..因此失败System.MissingMethodException
.
不幸的是,异常本身没有提供有关它正在寻找的方法的完整且准确的签名的足够信息,包括程序集名称.. 单独的类型名称欺骗性地看起来像是系统 dll 之一中存在的东西(mscorlib.dll
在这种情况下)..而不是便携式版本Newtonsoft.json.dll
.