我正在使用C#系统,并且一个类有一个返回System.Threading.Tasks.Task
对象的函数,并且有一个属性System.Type
ReturnType。
当ReturnType为null时,我知道该方法返回一个Task对象。但遗憾的是,没有办法知道实现接口的类是否会返回Task<ReturnType>
或Task<object>
,我需要获得此方法的结果。我认为最简单的方法是将Task<T>
转换为Task<object>
,这样我就可以得到结果并使用ReturnType中的Type值处理它。
如何在不知道T类型的情况下将Task<T>
转换为Task<object>
?
public interface ITaskFactory
{
ReadOnlyCollection<ParameterInfo> ParametersInfo { get; }
Type ReturnType { get; }
Task CreateTask (params object[] args);
}
我需要通过致电Task
CreateTask()
返回的结果
答案 0 :(得分:1)
我尝试了很多事情,唯一对我有用的事情是使用反射。我还添加了用于检测没有值的任务并引发异常的代码。
using System;
using System.Threading.Tasks;
using System.Reflection;
public class Program
{
private static async Task<object> Convert(Task task)
{
await task;
var voidTaskType = typeof (Task<>).MakeGenericType(Type.GetType("System.Threading.Tasks.VoidTaskResult"));
if (voidTaskType.IsAssignableFrom(task.GetType()))
throw new InvalidOperationException("Task does not have a return value (" + task.GetType().ToString() + ")");
var property = task.GetType().GetProperty("Result", BindingFlags.Public | BindingFlags.Instance);
if (property == null)
throw new InvalidOperationException("Task does not have a return value (" + task.GetType().ToString() + ")");
return property.GetValue(task);
}
public static async Task Main()
{
Console.WriteLine("Start");
Task i = CreateTask();
Task<object> o = Convert(i);
Console.WriteLine("value: {0}", await o);
Console.WriteLine("value2: {0}", await Convert(Task.FromResult<int>(123)));
//Test for tasks without return values
try
{
Console.WriteLine("value3: {0}", await Convert(Task.CompletedTask));
}
catch (Exception ex)
{
Console.WriteLine("value3: EX {0}", ex.Message);
}
//Test for tasks without return values
try
{
Console.WriteLine("value4: {0}", await Convert(Test4()));
}
catch (Exception ex)
{
Console.WriteLine("value4: EX {0}", ex.Message);
}
Console.WriteLine("Done");
}
private static Task CreateTask()
{
return Task.FromResult("Some result");
}
public static async Task Test4()
{
await Task.CompletedTask;
return;
}
}
答案 1 :(得分:0)
您的问题是如何转换通用代码。
尝试将任务创建为对象,然后从“转换”中删除类型参数。
using System;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
Task i = CreateTask();
Task<object> o = Convert<object>(i);
Console.WriteLine(o.Result);
}
private static async Task<T> Convert<T>(Task task)
{
return await ((Task<T>)task);
}
private static Task CreateTask ()
{
return Task.FromResult("Some result" as object);
}
}
答案 2 :(得分:-2)
Task<T>
is not协变(与IEnumerable<T>
不同,请参阅definition,注意out
keyword),因此您只能先等待它然后转换:
async Task<object> Do<T>(Task<T> task)
{
// this won't compile: Cannot implicitly convert type 'Task<T>' to 'Task<object>'
// return task;
object result = await task;
return result;
}
答案 3 :(得分:-2)
最简单的方法是使用ContinueWith
Task<T> task = null;
Task<object> obj = task.ContinueWith(t => (object)t.Result);