Reputation: 12424
I want to invoke a general Delegate
using async await
. I am not working with a prebuilt delegates, but rather the general Delegate
class which can receive arguments as an array of objects.
I am doing something like this:
public object InvokeAction(Delegate action, object[] actionArgs = null)
{
if(action == null)
{
return null;
}
return action.DynamicInvoke(args);
}
What I want to do is give an option to run the delegate using await
but since DynamicInvoke
returns an object, it doesn't have an awaiter
.
Is there a way to define a general delegate and make an asynchronous invocation? If not a generic one, is there some version which is close to a generic delegate (It's ok to force the user to some delegate definition) which can be invoked the way I want?
Upvotes: 3
Views: 1422
Reputation: 20354
Your delegate needs to return an awaitable type, generally this is Task
or Task<TResult>
.
You could check for this at runtime:
public async Task<TResult> InvokeAction<TResult>(Delegate action, object[] actionArgs = null)
{
//...
var result = action.DynamicInvoke(actionArgs);
if (result is Task<TResult> task) return await task;
return (TResult)result;
}
However, as long as actionArgs
are not modified within your method, you could statically type your delegate, and use a closure:
public async Task<TResult> InvokeAction<TResult>(Func<Task<TResult>> action)
{
//...
return await action();
}
var result = InvokeAction(() => YourMethodAsync(arg1, arg2));
Upvotes: 3
Reputation: 101443
I assume that IF target delegate references to method which is async (returns Task
or Task<T>
) then you want to execute it asynchronously. Then you can use method similar to your current one, but which is async:
public static async Task<object> InvokeActionAsync(Delegate action, object[] actionArgs = null)
{
if (action == null) {
return null;
}
// invoke it
var result = action.DynamicInvoke(actionArgs);
if (result == null)
return null;
if (result.GetType().IsGenericType && result.GetType().GetGenericTypeDefinition() == typeof(Task<>)) {
// this is some Task<T> which returns result
await (Task) result;
// now need to grab the result
return result.GetType().GetProperty("Result").GetValue(result);
}
else if (result is Task) {
// it's regular Task which does not return the value
await (Task) result;
return null;
}
// otherwise nothing to really run async, just return result
return result;
}
Upvotes: 1