c# - 具有可变输入的函数委托?
问题描述
我有一堆异步方法,它们都接受不同的输入,但它们都有相同的输出——一个名为HttpResponseData
(例如)的类的实例。
现在我想调用一个同步方法RunWithRetry
,它接受一个Func
委托输入(并返回HttpResponseData
)并运行它多次,直到某些条件变为真,如下面的示例代码:
public static async Task<HttpResponseData> RunWithRetry(Func<string, int, HttpResponseData> methodToRun,
string input1, int input2, int maxRetryCount = 10, int retryIntervalDelayInMs = 5000)
{
//some example usage code below where retry logic runs `methodToRun` as many times as needed
HttpResponseData responseData = null;
int triesDone = 0;
while (triesDone <= maxRetryCount && (responseData == null || responseData.StatusCode != HttpStatusCode.OK))
{
if (triesDone > 0)
Thread.Sleep(retryIntervalDelayInMs);
responseData = await Task.FromResult(methodToRun(input1, input2));
triesDone++;
}
return responseData;
}
问题是,Func<string, int, HttpResponseData> methodToRun
定义为上面的输入需要输入参数的特定组合(在本例中:)string, int
。这对我不起作用,因为正如我所说,我有许多不同的输入,它们都有不同的输入但输出相同:Task<HttpResponseData>
. 所以我不想RunWithRetry
用不同的输入集来指定这个方法的不同版本methodToRun
。
有没有办法可以定义Func
具有特定输出但可变/不同输入的泛型?
解决方案
首先,我推荐使用 Polly,这是一个经过良好测试且广泛使用的重试逻辑库。
但是要回答您最初的问题,您真正想要做的是将参数“绑定”到您的委托,然后使用绑定的委托。因此,与其定义一个采用委托及其参数的方法,不如定义采用已经绑定到其参数的委托的方法。
像这样:
公共静态异步任务<HttpResponseData> RunWithRetry(Func<HttpResponseData> methodToRun, int maxRetryCount = 10, int retryIntervalDelayInMs = 5000) { HttpResponseData 响应数据 = null; 整数尝试完成 = 0; while (triesDone <= maxRetryCount && (responseData == null || responseData.StatusCode != HttpStatusCode.OK)) { 如果(尝试完成> 0) Thread.Sleep(retryIntervalDelayInMs); responseData = await Task.FromResult(methodToRun()); 尝试完成++; } 返回响应数据; }
用法更改为使用 lambda 表达式将“运行方法”方法与其参数绑定:
// 旧用法: var response = await RunWithRetry(MethodToRun, "input1", 13, 10, 5000); // 新用法: var response = await RunWithRetry(() => MethodToRun("input1", 13), 10, 5000);
附带说明一下,await Task.FromResult
是一种反模式。我认为这只是示例代码或不完整的代码。适当的异步“运行方法”将使用异步委托类型,如下所示:
公共静态异步任务<HttpResponseData> RunWithRetry(Func<Task<HttpResponseData>> methodToRun, int maxRetryCount = 10, int retryIntervalDelayInMs = 5000) { HttpResponseData 响应数据 = null; 整数尝试完成 = 0; while (triesDone <= maxRetryCount && (responseData == null || responseData.StatusCode != HttpStatusCode.OK)) { 如果(尝试完成> 0) Thread.Sleep(retryIntervalDelayInMs); responseData = 等待方法ToRun(); 尝试完成++; } 返回响应数据; } // 用法: var response = await RunWithRetry(() => MethodToRunAsync("input1", 13), 10, 5000);
推荐阅读
- c# - 尝试将值输入列表的特定索引时出现 ArgumentOutOfRangeException?
- java - 当应用程序中没有流量时如何在 logback 中强制推出
- git - Jenkins Git 参数插件 branchFilter 正则表达式
- flutter - 如何从另一个小部件推送和弹出一个小部件(B 从 A 的转换)
- ruby - errno::eacces: 上传 jpg 时权限被拒绝@rb_sysopen
- flutter - 卡片上的 Flutter Text 叠加层
- c# - c# winforms中的图像单击选择下拉项目
- javascript - 向 Express 发送 AJAX POST 请求
- r - 具有某些列的点和图的ggplot
- python - 基于Python中的变量将n维numpy数组转换为二维数组