如何在C#</t>中T未知时动态创建Func <t>

时间:2012-01-18 23:37:01

标签: c# .net .net-4.0 func dynamically-generated

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

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 个答案:

答案 0 :(得分:2)

我认为你对你究竟需要什么感到困惑...从你展示的代码我会说你的Func必须返回object,你必须处理后面的对象的转换任务执行。向前迈出一步,如果你的Func是包含确定返回类型的逻辑的那个,你可以返回一个包含参数MyResultReturnObject的编组类ReturnType,然后执行后,您将ReturnObject转换为RetrunType对象。

答案 1 :(得分: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);
    }
}

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

我明白了。我首先使用它期望的签名创建了一个方法:

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

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

像魅力一样运行。