mardi 29 décembre 2020

Workaround on casting Task

Background
I am trying to get a method (using reflection), and turn it to a delegate (using Delegate.CreateDelegate() method), and to boost the performance, cast the resulting Delegate object to a Func<Task<BaseClass>> so I can call Invoke() instead of DynamicInvoke() which is very slow.
However, I get an run-time error: Unable to cast ....

Simplified
Consider this scenario: Task<object> foo = (Task<string>)null;, where I want to cast Task<string> to Task<object> and it raises an error. Obviously because of the fact that Task<> is not contravariant.
If I wrap the Task<T> into another class (say Taskwrapper<out T>) and implement its implicit conversion, then Taskwrapper wouldn't be awaitable. Based on this issue on GitHub, I can now use ITask interface. But the code is not popular enough (or Microsoft-referenced) to rely on.
I'd like to know if any other way to cast Task<DeriveClass> to Task<BaseClass>? Or any alternative that keeps my method awaitable.

Some code

var genericTask = typeof(Task<>).MakeGenericType(dynamicOutputType);
var genericFunc = typeof(Func<>).MakeGenericType(genericTask);
var getResultDelegate = Delegate.CreateDelegate(genericFunc, result.ActionObject, "GetResult");
methodGetResult = (Func<Task<object>>)getResultDelegate; -- runtime Error here!

I want to cache the above methodGetResult variable and reuse it like this: cachedElements.MethodGetResult.Invoke(inputValue);





Aucun commentaire:

Enregistrer un commentaire