0

我有一个返回值的任务,但我想将该值转换为其他值(例如, from stringto int)。这通常很容易做到,我所做的只是添加执行转换并返回新类型的延续任务,如下所示:

ConverterService converter = ...;
Task<string> originalTask = Task.Factory.FromAsync<string>(...);
Task<int> conversionTask = originalTask.ContinueWith(p => converter.Convert(typeof(string), typeof(int), p.Result));

问题是类型未知:(我已经能够动态生成 originalTask​​。这是我脑海中的摘录:

ConverterService converter = ...;
// dynamically calling Task.Factory.FromAsync
var originalTask = FromAsyncMethodInfo.Invoke(Task.Factory, args.ToArray());
...

// now I want to dynamically call Task<string>.ContinueWith
var conversionTask = ContinueWithMethodInfo.Invoke(originalTask, ???)

现在我该怎么做?我希望为它提供一个Func<Task<T>, U>(在这个例子中确实Func<Task<string>, int>如此),但我如何动态生成它?

为简单起见,我只想知道Func<T>当我只有一个Type变量时如何在运行时动态创建一个。或者是第一个代码块中看到的 lambda 的动态生成替代方案:

Task<int> conversionTask = originalTask.ContinueWith(p => converter.Convert(typeof(string), typeof(int), p.Result));

提前谢谢了。

4

4 回答 4

2

我认为你对你到底需要什么有点困惑......从你展示的代码中我会说你的 Func 必须返回object,并且你必须在任务执行后处理对象的转换。更进一步,如果你的 Func 是包含确定返回类型的逻辑的那个,你可以返回一个组成的 class MyResult,它有参数ReturnObjectReturnType,然后在执行之后你会强制ReturnObject转换为一个RetrunType对象。

于 2012-01-19T00:13:57.210 回答
2

您可以使用Task<object>该项目并将其作为object. 您可以使用 获取对象的类型object.GetType()。这是一个例子:

void Main()
{
    var conversion = new ConversionService();
    var wantedType = typeof(string);

    Task<object> originalTask = Task<object>.Factory.StartNew(
       () => { /* test impl */ return 1; }); 

    var nextTask = originalTask.ContinueWith(prev =>
       conversion.ConvertObject(prev.Result.GetType(), wantedType, prev.Result));

    var result = nextTask.Result;
    Console.WriteLine("{0} - {1}", result.GetType(), result);
}

class ConversionService
{
    public object ConvertObject(Type source, Type dest, object input)
    {
        // test impl.
        return Convert.ChangeType(input, dest);
    }
}
于 2012-01-19T04:13:35.743 回答
0

您无法Func<TIn, TOut>动态生成 a,因为您需要提供进行转换的逻辑,并且在类型已知之前,您无法提供逻辑。

例如,如果要将 int 转换为 string,则可以调用 ToString(),而如果要朝另一个方向进行,则可以使用 int.TryParse()。如果您有一组有限的可能转换,则可以使用某种机制在已构建的委托集合中进行运行时查找,但是无法生成可以将一种类型的值任意转换为任何其他类型的代码。

于 2012-01-19T00:28:22.960 回答
0

我想到了。我首先创建了一个带有预期签名的方法:

public TOutput HandleTask<TTaskInput, TOutput>(TTaskInput task)

此方法处理转换和异常处理。然后,我使用 Delegate.CreateDelegate 为该方法创建一个委托实例,然后将其传递给动态 ContinueWith 调用。

像魅力一样运行。

于 2012-01-19T16:24:26.833 回答