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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With