2013-07-29 16 views
4

我已經寫了一個小的異步庫包裝到Json.Net v5.06從NuGet和更新了一些Telerik包後,我的UnitTests開始失敗,MissingMethodException從異步序列化操作MissingMethodException

我已經創建了一個虛擬的非Async方法,它的工作原理讓我很困惑,錯誤在哪裏。

項目目標平臺

.NET 4.5

的x86 CPU

異步操作

public class JsonSerialiser : ISerialiser 
    { 

     [InjectionConstructor] 
     public JsonSerialiser(IStringCompression streamCompressor, ILog logger) 
     { 
      if (streamCompressor == null) throw new ArgumentNullException("streamCompressor"); 
      if (logger == null) throw new ArgumentNullException("logger"); 

      XmlConfigurator.Configure(); 

      this.streamCompressor = streamCompressor; 
      this.logger = logger; 
     } 


     public async Task<string> SerialiseAsync<T>(T serialseObject) where T : class 
     { 
      if (serialseObject == null) throw new ArgumentNullException("serialseObject"); 

      try 
      { 
       return await JsonConvert.SerializeObjectAsync(serialseObject); 
      } 
      catch (JsonSerializationException ex) 
      { 
       logger.Error(ex); 
       throw new SerialisationException("Could Not Serialse The Object", ex); 
      } 
     } 
    } 

異步實施例

現在,這段代碼被放在一起,只是爲了測試基本的序列化,在那裏我跨過類構造函數中的空檢查。

private async void button1_Click(object sender, EventArgs e) 
    { 
     List<Part> parts = new List<Part> { new Part() { AbstractType = typeof(IOpcController), ConcreteType = typeof(OpcController) }, 
               new Part() { AbstractType = typeof(ISerialiser), ConcreteType = typeof(JsonSerialiser) }, 
               new Part() { AbstractType = typeof(IStringCompression), ConcreteType = typeof(StringGZipCompression)}}; 

     string serialisedResult = string.Empty; 
     JsonSerialiser serialiser = new JsonSerialiser(null, null); 
     serialisedResult = await serialiser.SerialiseAsync<List<Part>>(parts); 
    } 

異步結果

這一代的MissingMethodException

enter image description here

Method not found: 'System.Threading.Tasks.Task`1<System.String> Newtonsoft.Json.JsonConvert.SerializeObjectAsync(System.Object)'. 

    at Helper.Core.Serialisation.Json.JsonSerialiser.<SerialiseAsync>d__0`1.MoveNext() 
    at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) 
    at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.Start[TStateMachine](TStateMachine& stateMachine) 
    at Helper.Core.Serialisation.Json.JsonSerialiser.SerialiseAsync[T](T serialseObject) 
    at OpcTester.Form1.<button1_Click>d__9.MoveNext() in c:\Users\phil.murray\Desktop\tmp\OpcTester\Form1.cs:line 44 

無異步操作

只是爲了檢查是否是導致問題的方法的異步部分,我寫了一個沒有異步的實現。

public string Serialise<T>(T serialseObject) where T : class 
{ 
    if (serialseObject == null) throw new ArgumentNullException("serialseObject"); 

    try 
    { 
     return JsonConvert.SerializeObject(serialseObject); 
    } 
    catch (JsonSerializationException ex) 
    { 
     logger.Error(ex); 
     throw new SerialisationException("Could Not Serialse The Object", ex); 
    } 
} 

無異步執行

private async void button1_Click(object sender, EventArgs e) 
{ 
    List<Part> parts = new List<Part> { new Part() { AbstractType = typeof(IOpcController), ConcreteType = typeof(OpcController) }, 
              new Part() { AbstractType = typeof(ISerialiser), ConcreteType = typeof(JsonSerialiser) }, 
              new Part() { AbstractType = typeof(IStringCompression), ConcreteType = typeof(StringGZipCompression)}}; 

    string serialisedResult = string.Empty; 
    JsonSerialiser serialiser = new JsonSerialiser(null, null); 
    serialisedResult = serialiser.Serialise<List<Part>>(parts); 
} 

無異步結果

的方法完成,串行化列表到字符串。

失敗的測試例

Test Name: SerialiserSerialiseObjectExists 
    Test FullName: Helper.Tests.SerialiserTests.SerialiserSerialiseObjectExists 
    Test Source: c:\Perforce\Development\SharedAPIs\Helper.Core\Helper.Tests\SerialiserTests.cs : line 38 
    Test Outcome: Failed 
    Test Duration: 0:00:00.0116216 

    Result Message: 
    Test method Helper.Tests.SerialiserTests.SerialiserSerialiseObjectExists threw exception: 
    System.MissingMethodException: Method not found: 'System.Threading.Tasks.Task`1<System.String> Newtonsoft.Json.JsonConvert.SerializeObjectAsync(System.Object)'. 
    Result StackTrace: 
    at Helper.Core.Serialisation.Json.JsonSerialiser.<SerialiseAsync>d__0`1.MoveNext() 
     at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) 
     a 

t System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.Start[TStateMachine](TStateMachine& stateMachine) 
    at Helper.Core.Serialisation.Json.JsonSerialiser.SerialiseAsync[T](T serialseObject) 
    at Helper.Tests.SerialiserTests.<SerialiserSerialiseObjectExists>d__3.MoveNext() in c:\Perforce\Development\SharedAPIs\Helper.Core\Helper.Tests\SerialiserTests.cs:line 40 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.GetResult() 

異步爲了討論我更換了Json.Net呼叫與虛擬任務和它的工作,所以它看起來像沒有測試Json.Net

問題在於使用Await \ Async調用Json.net。奇怪,因爲這是工作和版本尚未更新。

public async Task<string> SerialiseAsync<T>(T serialseObject) where T : class 
{ 
    if (serialseObject == null) throw new ArgumentNullException("serialseObject"); 

    try 
    { 
     //return await JsonConvert.SerializeObjectAsync(serialseObject); 
     return await Task.Run(() => string.Empty); 
    } 
    catch (JsonSerializationException ex) 
    { 
     logger.Error(ex); 
     throw new SerialisationException("Could Not Serialse The Object", ex); 
    } 
} 

問題

現在異步方法單元測試之前工作我更新前的Telerik控制套件,我做了一些真實世界的實例的測試操作。我並不是說Telerik更新引發了這個問題,因爲這可能是巧合。當測試其他類時(與Json.Net無關),許多其他異步測試用例都會通過。

任何想法異步方法有什麼問題以及如何解決問題?

可能的解決

當我繼續研究它發生,我認爲問題可能出在Json.Net庫中的異步調用,所以我wrappered在任務中沒有異步調用的問題,下面,其工作

public async Task<string> SerialiseAsync<T>(T serialseObject) where T : class 
    { 
     if (serialseObject == null) throw new ArgumentNullException("serialseObject"); 

     try 
     { 
      //return await JsonConvert.SerializeObjectAsync(serialseObject); 
      return await Task.Run<string>(() => JsonConvert.SerializeObject(serialseObject)); 
     } 
     catch (JsonSerializationException ex) 
     { 
      logger.Error(ex); 
      throw new SerialisationException("Could Not Serialse The Object", ex); 
     } 
    } 

出於興趣我下載了Json.Net源和檢查了JsonConvert.SerializeObjectAsync呼叫,它是做同樣的事情,所以我又不能確定潛在的問題。

public static Task<string> SerializeObjectAsync(object value, Formatting formatting, JsonSerializerSettings settings) 
{ 
    return Task.Factory.StartNew(() => SerializeObject(value, formatting, settings)); 
} 
+0

你試過重新安裝Json.net嗎? –

+0

是的,我試過的第一件事。 –

回答

0

檢查包含正在執行的程序集的輸出目錄。 在Newtonsoft.Json.dll屬性裏面你會看到描述是「Json.Net Portable .Net 4.0」,這個版本沒有提供SerializeObjectAsync(你可以使用ILSpy來檢查程序集)。

enter image description here

通過淨替換的Json裝配4.5版本,它應該工作。

+0

該DLL是NuGet軟件包的net45文件夾中的版本。文件說明 - Json.Net;文件版本 - 5.0.6.16206。 –

+0

它看起來像你的AppDomain中加載的程序集不是net45版本。您可以使用fuslogvw來檢查使用哪個程序集,或手動列出AppDomain中加載的程序集。 – Guillaume