0

假設我有一個返回任務爲對象的API:如何鏈,另一個任務的任務不知道第一個任務的結果類型

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

應該打印 「任務字符串」 字符串。

與WrapTask功能的問題是,編譯器拒絕接受這種結構:

 object result = task.ContinueWith(parentTask => parentTask.Result, TaskContinuationOptions.ExecuteSynchronously); 

,出現以下錯誤:

 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。

回答

2

你可以使用動態類型調用由動態類型提供了類型推斷的一般方法:

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

這根本不清楚這是什麼捆綁的一點是,你要知道......也不知道爲什麼你只想投結果WrapTask - 如果你知道這是一個任務,爲什麼不把結果CreateTask代替,在這一點上,你可以簡單地調用WrapTask?或者也許讓WrapTask執行鑄造本身?

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); 
+0

上面的API是一種簡化。真實情況簡而言之:有一個API(一組方法)返回任務。每種方法的TResult可能不同。我需要設計一個解決方案,允許將調用記錄到實現該API的對象。我認爲這是一個方面的工作。爲了搭建這個方面,我使用了Unity的攔截功能。因此,攔截器在API返回的原始任務上創建了一個延續。在這個延續中實現了日誌方面。然後,攔截器應該返回呼叫站點預期的任務。 –

+0

其中TResult是原始任務的實際結果。爲什麼'對象'你問。這是因爲在攔截器的結果是通過IMethodReturn.ReturnValue這是'對象'的實例可用。或者我仍然失去了一些東西? –

+0

@ ay.metallo:對 - 這樣做更有意義。當你呈現看似毫無意義的任務時,它總是解釋爲什麼它不是毫無意義的。 –

相關問題