Generics 如何在不知道第一个任务的情况下将一个任务链接到另一个任务';s结果类型
假设我有一个将任务作为对象返回的API:Generics 如何在不知道第一个任务的情况下将一个任务链接到另一个任务';s结果类型,generics,reflection,expression-trees,task-parallel-library,Generics,Reflection,Expression Trees,Task Parallel Library,假设我有一个将任务作为对象返回的API: private static object CreateTask() { return Task.Factory.StartNew(() => "Task string"); } 我需要使用一个函数扩展API,该函数返回另一个链接到CreateTask函数返回的任务的任务,以便新任务的结果将是初始任务的结果。也就是说,类似这样的事情: private static object WrapTask(d
private static object CreateTask()
{
return Task.Factory.StartNew(() => "Task string");
}
我需要使用一个函数扩展API,该函数返回另一个链接到CreateTask函数返回的任务的任务,以便新任务的结果将是初始任务的结果。也就是说,类似这样的事情:
private static object WrapTask(dynamic task)
{
object new_task = task.ContinueWith(parentTask => parentTask.Result, TaskContinuationOptions.ExecuteSynchronously);
return new_task;
}
使用示例:
var task = (Task<string>)WrapTask(CreateTask());
Console.WriteLine(task.Result);
出现以下错误:
Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type
如果您有任何关于如何以所述方式扩展API的想法,我们将不胜感激。您可以使用动态类型调用泛型方法,并使用动态类型提供的类型推断:
private static object WrapTask(dynamic task)
{
return WrapTaskImpl(task);
}
private static Task<T> WrapTaskImpl<T>(Task<T> task)
{
return task.ContinueWith(parentTask => parentTask.Result,
TaskContinuationOptions.ExecuteSynchronously);
}
然后您的呼叫代码变为
var task = WrapTask<string>(CreateTask());
Console.WriteLine(task.Result);
var task=WrapTask(CreateTask());
Console.WriteLine(task.Result);
上述API是一种简化。简而言之,实际情况是:有一个API(一组方法)返回任务。每个方法的结果可能不同。我需要设计一个解决方案,允许记录对实现该API的对象的调用。我想这是一个方面的工作。为了连接那个相位,我使用Unity的截取。因此,拦截器在API返回的原始任务上创建一个延续。在此延续中,实现了日志方面。然后,拦截器应该返回调用站点期望的任务,其中TResult是原始任务的实际结果。你为什么要问“反对”。。这是因为在拦截器中,结果可通过IMethodReturn.ReturnValue的实例获得,该实例为“object”。。或者我还缺少什么?@ay.metallo:对-这更有意义。当你呈现一个看似毫无意义的任务时,它总是在解释为什么它不是真正毫无意义的。顺便说一句,感谢你提供了优雅的解决方案(我一直都知道它一定是简单的;动力学确实很强大)!看起来还可以。@ay.metallo:那么您使用的是哪种解决方案?如果你能用后者,我会。。。
private static Task<T> WrapTask<T>(object task)
{
Task<T> realTask = (Task<T>) task;
return realTask.ContinueWith(parentTask => parentTask.Result,
TaskContinuationOptions.ExecuteSynchronously);
}
var task = WrapTask<string>(CreateTask());
Console.WriteLine(task.Result);