我有一个函数可以加载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参数需要节点的加载功能。用法如下
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?);
}
简而言之,问题是如何使用回调函数返回包装函数的结果?
答案 0 :(得分: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");