AsyncToSyncAdapter
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security;
using System.Threading;
namespace NUnit.Framework.Internal
{
internal static class AsyncToSyncAdapter
{
private const string TaskWaitMethod = "Wait";
private const string TaskResultProperty = "Result";
private const string VoidTaskResultType = "VoidTaskResult";
private const string SystemAggregateException = "System.AggregateException";
private const string InnerExceptionsProperty = "InnerExceptions";
private const BindingFlags TaskResultPropertyBindingFlags = BindingFlags.Instance | BindingFlags.Public;
public static bool IsAsyncOperation(MethodInfo method)
{
if (!IsTaskType(method.ReturnType))
return method.GetCustomAttributes(false).Any((object attr) => attr.GetType().FullName == "System.Runtime.CompilerServices.AsyncStateMachineAttribute");
return true;
}
public static bool IsAsyncOperation(Delegate delegate)
{
return IsAsyncOperation(delegate.GetMethodInfo());
}
private static bool IsTaskType(Type type)
{
while (type != (Type)null) {
if (type.GetTypeInfo().IsGenericType ? (type.GetGenericTypeDefinition().FullName == "System.Threading.Tasks.Task`1") : (type.FullName == "System.Threading.Tasks.Task"))
return true;
type = type.GetTypeInfo().BaseType;
}
return false;
}
public static object Await(Func<object> invoke)
{
Guard.ArgumentNotNull(invoke, "invoke");
object obj = default(object);
using (InitializeExecutionEnvironment()) {
obj = invoke();
if (obj == null || !IsTaskType(obj.GetType()))
throw new InvalidOperationException("The delegate did not return a Task.");
AwaitAdapter awaitAdapter = AwaitAdapter.FromAwaitable(obj);
if (!awaitAdapter.IsCompleted)
MessagePumpStrategy.FromCurrentSynchronizationContext().WaitForCompletion(awaitAdapter);
}
try {
obj.GetType().GetMethod("Wait", new Type[0]).Invoke(obj, null);
} catch (TargetInvocationException ex) {
ExceptionHelper.Rethrow(GetAllExceptions(ex.InnerException)[0]);
}
Type[] genericArguments = obj.GetType().GetGenericArguments();
if (genericArguments.Length == 1 && genericArguments[0].Name == "VoidTaskResult")
return null;
PropertyInfo property = obj.GetType().GetProperty("Result", BindingFlags.Instance | BindingFlags.Public);
if (!(property != (PropertyInfo)null))
return obj;
return property.GetValue(obj, null);
}
private static IDisposable InitializeExecutionEnvironment()
{
return null;
}
[SecuritySafeCritical]
private static void SetSynchronizationContext(SynchronizationContext syncContext)
{
SynchronizationContext.SetSynchronizationContext(syncContext);
}
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
};
}
}
}