我已經寫了一個小的異步庫包裝到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
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));
}
你試過重新安裝Json.net嗎? –
是的,我試過的第一件事。 –