将您的流利方法重写为这种形式 - 即,将它们作为扩展方法几乎没有意义:
public static async Task<ResultType> Transform(SourceType original)
{
// some async work
var transformed = await DoSomething(original)
return transformed;
}
提供这些通用扩展方法(与@Gennadii Saltyshchak 的 PipeSync 方法几乎相同,但我发现“Then”这个名字更简洁):
public static async Task<T2> Then<T1, T2>(this T1 first, Func<T1, Task<T2>> second)
{
return await second(first).ConfigureAwait(false);
}
public static async Task<T2> Then<T1, T2>(this Task<T1> first, Func<T1, Task<T2>> second)
{
return await second(await first.ConfigureAwait(false)).ConfigureAwait(false);
}
public static async Task<T2> Then<T1, T2>(this Task<T1> first, Func<T1, T2> second)
{
return second(await first.ConfigureAwait(false));
}
public static Task<T2> Then<T1, T2>(this T1 first, Func<T1, T2> second)
{
return Task.FromResult(second(first));
}
然后你可以像这样构建一个流畅的链:
var processed = await Transform1(source)
.Then(Transform1)
.Then(Transform2)
.Then(Transform3);
由于 Then() 重载,这适用于异步/同步方法的任何排列。
如果例如Transform2 需要参数,你需要扩展为一个 lambda:
var processed = await Transform1(source)
.Then(Transform1)
.Then(x => Transform2(x, arg1, arg2))
.Then(Transform3);
我认为这与使用当前语言所能获得的流畅的异步链一样接近!
应尽可能使用 ValueTask 优化异步/同步的组合。给读者的练习! :-)