Reputation: 13448
Related to Casting TResult in Task<TResult> to System.Object. I am building a generic async command execution function for a service.
The method to execute a generic command looks like this:
public async Task<object> ExecuteCommandAsync(string cmdName, CommandData data)
The code uses reflection to find a method on the class that has the given cmdName
. Invoking this will return a Type<T>
- we don't know the T
in advance. However since Task<T>
is not covariant, I cannot cast to Task<object>
.
At present my solution (as per 21805564) is to call the Result method and encapsulate in a Task.Run
, as shown below:
// find the method
MethodInfo cmd = GetMethod(cmdName);
var task = (Task)cmd.Invoke(this, data);
return await Task.Run<object>(() => { return task.GetType().GetProperty("Result").GetValue(task); });
My concern is that doing this negates the value of async: getting the result is now a blocking call so I might as well have used synchronous methods anyway.
Upvotes: 4
Views: 2021
Reputation: 456407
Remember that dynamic
is available. You can do something like this as long as you're not using Microsoft.Bcl.Async
:
public async Task<dynamic> ExecuteCommandAsync(string cmdName, CommandData data)
{
MethodInfo cmd = GetMethod(cmdName);
dynamic task = cmd.Invoke(this, data);
return await task;
}
In particular, I don't recommend using Task.Run
because that would waste a thread, and I don't recommend using Task.Result
because it will encapsulate any exceptions inside an AggregateException
.
Upvotes: 5
Reputation: 144126
You can await the task and then reflect on the result once it has completed
public static async Task<object> AwaitResult(Task t)
{
await t;
return t.GetType().GetProperty("Result").GetValue(t, null);
}
Or:
return ((dynamic)t).Result;
Upvotes: 5