public static Type GetReturnType(this MethodInfo methodInfo) { Check.NotNull(methodInfo, nameof(methodInfo)); var isAwaitable = CoercedAwaitableInfo.IsTypeAwaitable(methodInfo.ReturnType, out var coercedAwaitableInfo); return(isAwaitable ? coercedAwaitableInfo.AwaitableInfo.ResultType : methodInfo.ReturnType); }
public static bool IsAsyncMethodInfo([NotNull] this MethodInfo methodInfo) { Check.NotNull(methodInfo, nameof(methodInfo)); var isAwaitable = CoercedAwaitableInfo.IsTypeAwaitable(methodInfo.ReturnType, out var coercedAwaitableInfo); return(isAwaitable); }
private ObjectMethodExecutor(MethodInfo methodInfo, TypeInfo targetTypeInfo, object?[]?parameterDefaultValues) { if (methodInfo == null) { throw new ArgumentNullException(nameof(methodInfo)); } MethodInfo = methodInfo; MethodParameters = methodInfo.GetParameters(); TargetTypeInfo = targetTypeInfo; MethodReturnType = methodInfo.ReturnType; var isAwaitable = CoercedAwaitableInfo.IsTypeAwaitable(MethodReturnType, out var coercedAwaitableInfo); IsMethodAsync = isAwaitable; AsyncResultType = isAwaitable ? coercedAwaitableInfo.AwaitableInfo.ResultType : null; // Upstream code may prefer to use the sync-executor even for async methods, because if it knows // that the result is a specific Task<T> where T is known, then it can directly cast to that type // and await it without the extra heap allocations involved in the _executorAsync code path. _executor = GetExecutor(methodInfo, targetTypeInfo); if (IsMethodAsync) { _executorAsync = GetExecutorAsync(methodInfo, targetTypeInfo, coercedAwaitableInfo); } _parameterDefaultValues = parameterDefaultValues; }