2013-02-05 105 views
0

我有一個函數可以加載一個Node的子節點。它在內部調用一個WCF異步服務來加載。簽名如下。樹加載器擴展函數內的異步函數調用

public void AddChildElements(Node parentElement, 
            Action<IEnumerable<Node>> callback) 
{ 

} 

這可以用於像

_nodeBuilder.AddChildElements(parentElement, (elements) => 
       { 
       //do something with elements 
       }); 

現在我想編寫一個函數來擴展基於某些條件下的層次結構。所以我寫這樣的

public static T LoadHierarchyUntilItemFound<T>(
     this IEnumerable<T> sequence, Func<T, List<T>> loadaction, 
     Func<T, string> searchstring) 
{ 
    //... 
} 

的loadaction參數擴展功能預計爲node.The使用加載功能如下

Elements.LoadHierarchyUntilItemFound(LoadChildren,        
            "root.UK.England.London"); 

的問題是我如何寫一個加載函數?

private List<Node> LoadChildren(Node parent) 
    { 
      // _nodeBuilder.AddChildElements(parent, here it expects a callback 
         //which gives the result, how to use this?); 
    } 

總之,麻煩在於如何使用回調函數來返回包裝函數的結果?

回答

1

如果你真的想可能只是使調用異步方法和塊,直到它返回一個函數:

private List<Node> LoadChildren(Node parent) 
{ 
    var tcs = new TaskCompletionSource<IEnumerable<Node>>(); 

    AddChildElements(parent, nodes => tcs.SetResult(nodes)); 

    return tcs.Task.Result.ToList(); 
} 

然而,在許多情況下這將是最好做這整個事情異步,而不是同步。

public static async Task<T> LoadHierarchyUntilItemFoundAsync<T>(
    this IEnumerable<T> sequence, Func<T, Task<IEnumerable<T>>> loadaction, 
    Func<T, string> selector, string searchstring) 
{ 
    var stack = new Stack<T>(sequence); 
    while (stack.Any()) 
    { 
     var item = stack.Pop(); 

     if (selector(item) == searchstring) 
      return item; 

     foreach (var child in await loadaction(item)) 
     { 
      stack.Push(child); 
     } 
    } 

    return default(T); 
} 

鑑於這樣你可以使用它調用一個函數:

Elements.LoadHierarchyUntilItemFound(AddChildElements,        
           "root.UK.England.London"); 
+0

+1,真正體會到了答案。謝謝。 – Jimmy