AsyncInvocationRegion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.ExceptionServices;
namespace NUnit.Framework.Internal
{
internal abstract class AsyncInvocationRegion : IDisposable
{
private class AsyncTaskInvocationRegion : AsyncInvocationRegion
{
private const string TaskWaitMethod = "Wait";
private const string TaskResultProperty = "Result";
private const string SystemAggregateException = "System.AggregateException";
private const string InnerExceptionsProperty = "InnerExceptions";
private const BindingFlags TaskResultPropertyBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty;
public override object WaitForPendingOperationsToComplete(object invocationResult)
{
try {
invocationResult.GetType().GetMethod("Wait", new Type[0]).Invoke(invocationResult, null);
} catch (TargetInvocationException ex) {
IList<Exception> allExceptions = GetAllExceptions(ex.InnerException);
ExceptionDispatchInfo.Capture(allExceptions[0]).Throw();
}
PropertyInfo property = invocationResult.GetType().GetProperty("Result", BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);
if (!(property != (PropertyInfo)null))
return invocationResult;
return property.GetValue(invocationResult, null);
}
private static IList<Exception> GetAllExceptions(Exception exception)
{
if ("System.AggregateException".Equals(exception.GetType().FullName))
return (IList<Exception>)exception.GetType().GetProperty("InnerExceptions").GetValue(exception, null);
return new Exception[1] {
exception
};
}
}
private const string TaskTypeName = "System.Threading.Tasks.Task";
private const string AsyncAttributeTypeName = "System.Runtime.CompilerServices.AsyncStateMachineAttribute";
private AsyncInvocationRegion()
{
}
public static AsyncInvocationRegion Create(Delegate delegate)
{
return Create(delegate.Method);
}
public static AsyncInvocationRegion Create(MethodInfo method)
{
if (!IsAsyncOperation(method))
throw new ArgumentException("Either asynchronous support is not available or an attempt \r\nat wrapping a non-async method invocation in an async region was done");
if (method.ReturnType == typeof(void))
throw new ArgumentException("'async void' methods are not supported, please use 'async Task' instead");
return new AsyncTaskInvocationRegion();
}
public static bool IsAsyncOperation(MethodInfo method)
{
if (!method.ReturnType.FullName.StartsWith("System.Threading.Tasks.Task"))
return method.GetCustomAttributes(false).Any((object attr) => "System.Runtime.CompilerServices.AsyncStateMachineAttribute" == attr.GetType().FullName);
return true;
}
public static bool IsAsyncOperation(Delegate delegate)
{
return IsAsyncOperation(delegate.Method);
}
public abstract object WaitForPendingOperationsToComplete(object invocationResult);
public virtual void Dispose()
{
}
}
}