Damien_The_Unbeliever threw an interesting challenge. I think checking for AsyncStateMachineAttribute
isn't a sufficient solution. The original question shouldn't be whether the method is async. Instead it should be whether it's awaitable. Both method samples in Damien's answer will return true if you check for the method GetAwaiter()
on the return type. However, only the method marked async
will include the AsyncStateMachineAttribute
in the custom attributes collection.
Knowing if the method is awaitable is important if you want to use MethodInfo.Invoke()
to call the method and you don't know ahead of time if methods that might be registered to a message broker are awaitable.
var isAwaitable = _methodInfo.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null;
object result = null;
if (isAwaitable)
{
result = await (dynamic)_methodInfo.Invoke(_instance, _parameterArray);
}
else
{
result = _methodInfo.Invoke(_instance, _parameterArray);
}
EDIT:
Good idea to check the return type on MethodInfo. This is my revised code.
var isAwaitable = _methodInfo.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null;
object invokeResult = null;
if (isAwaitable)
{
if (_methodInfo.ReturnType.IsGenericType)
{
invokeResult = (object)await (dynamic)_methodInfo.Invoke(_instance, arguments);
}
else
{
await (Task)_methodInfo.Invoke(_instance, arguments);
}
}
else
{
if (_methodInfo.ReturnType == typeof(void))
{
_methodInfo.Invoke(_instance, arguments);
}
else
{
invokeResult = _methodInfo.Invoke(_instance, arguments);
}
}