如何为异步方法创建通用扩展方法?
How to create a generic extension method for async methods?
我正在尝试创建一个 .WithDelay(seconds);
方法,我可以在异步方法调用结束时添加它。
我遇到的问题是先调用异步方法然后发生延迟,我希望反过来,不切换调用顺序。
例如,我想要 await MyMethod().WithDelay(seconds);
而不是 await WithDelay(seconds).MyMethod();
。
这是我目前所拥有的,它首先调用方法:
public async static Task<T> WithDelay<T>(this Task<T> task, int delay) {
await Task.Delay(delay);
return await task;
}
我希望延迟先发生,然后才是实际方法 运行。
I want it the other way around, without switching the order of the call.
这是不可能的,因为 C# 语言只支持 types 的扩展方法,不支持 methods.
最接近的是委托的扩展方法:
public static async Task<T> WithDelay<T>(this Func<Task<T>> func, int delay) {
await Task.Delay(delay);
return await func();
}
用法还是很尴尬:
// Either:
Func<Task<MyType>> func = MyMethod;
var result = await func.WithDelay(1000);
// or (assuming "using static"):
var result = await WithDelay(MyMethod, 1000);
// What you really want, not currently possible:
// var result = await MyMethod.WithDelay(1000);
对于像这样与类型相关的情况,它可以帮助先同步解决问题,然后将该解决方案转换为async
。如果语言阻止了良好的同步解决方案,那么它很可能会阻止良好的异步解决方案。
方法上有一个 proposal 扩展方法,但它不是今天语言的一部分。
下面行不行?
public static Task Async<T>(this T o, Action<T> action, CancellationToken token = default) {
if (token.IsCancellationRequested) {
return Task.FromCanceled(token);
}
try {
action(o);
return Task.CompletedTask;
} catch (Exception e) {
return Task.FromException(e);
}
}
示例:
public static Task CommitAsync(this IDbTransaction transaction, CancellationToken token = default)
=> transaction.Async(x=> transaction.Commit(), token);
我正在尝试创建一个 .WithDelay(seconds);
方法,我可以在异步方法调用结束时添加它。
我遇到的问题是先调用异步方法然后发生延迟,我希望反过来,不切换调用顺序。
例如,我想要 await MyMethod().WithDelay(seconds);
而不是 await WithDelay(seconds).MyMethod();
。
这是我目前所拥有的,它首先调用方法:
public async static Task<T> WithDelay<T>(this Task<T> task, int delay) {
await Task.Delay(delay);
return await task;
}
我希望延迟先发生,然后才是实际方法 运行。
I want it the other way around, without switching the order of the call.
这是不可能的,因为 C# 语言只支持 types 的扩展方法,不支持 methods.
最接近的是委托的扩展方法:
public static async Task<T> WithDelay<T>(this Func<Task<T>> func, int delay) {
await Task.Delay(delay);
return await func();
}
用法还是很尴尬:
// Either:
Func<Task<MyType>> func = MyMethod;
var result = await func.WithDelay(1000);
// or (assuming "using static"):
var result = await WithDelay(MyMethod, 1000);
// What you really want, not currently possible:
// var result = await MyMethod.WithDelay(1000);
对于像这样与类型相关的情况,它可以帮助先同步解决问题,然后将该解决方案转换为async
。如果语言阻止了良好的同步解决方案,那么它很可能会阻止良好的异步解决方案。
方法上有一个 proposal 扩展方法,但它不是今天语言的一部分。
下面行不行?
public static Task Async<T>(this T o, Action<T> action, CancellationToken token = default) {
if (token.IsCancellationRequested) {
return Task.FromCanceled(token);
}
try {
action(o);
return Task.CompletedTask;
} catch (Exception e) {
return Task.FromException(e);
}
}
示例:
public static Task CommitAsync(this IDbTransaction transaction, CancellationToken token = default)
=> transaction.Async(x=> transaction.Commit(), token);