在不知道typeof T </t>的情况下获得Task <t>的结果

时间:2014-03-01 02:13:29

标签: c# .net task-parallel-library

我正在使用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()返回的结果

请参阅:http://dotnetfiddle.net/Bqwz0I

4 个答案:

答案 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);
    }
}

https://dotnetfiddle.net/VobcWY

答案 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);