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.
Passes - I presume an exe, which calls into PCL1, which calls into portable version of NewtonSoft.Json.dll
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
.
Newtonsoft.Json
referenced only from first the PCL where it used, or are there other non-PCL assemblies (or may be even PCL assemblies with different profile) which also referenceNewtonsoft.Json
. In other words, when this code doesn't work, which all assemblies referenceNewtonsoft.Json
, and what are their profiles? On the flip side, when it does work, isNewtonsoft.Json
referenced only from one assembly, the PCL which contains above code? – Entree