我的问题是这样的。我有几个功能:
public List<FtpDirectoryEntry> ListDirectory();
public bool DirectoryExists(string dir);
public void UploadFile(string file);
public void UploadFiles(params string[] files);
我想编写一个函数来运行这些函数5次。如果我们无法获得5次结果,它将抛出异常。
public void CheckFunctionWithTrials( function X)
{
for (int i = 0; i < 5; i++)
{
try
{
X;
break;
}
catch (Exception e)
{
if (i == 5 - 1)
{
throw e;
}
else
{
DLog.Warn("Failed to upload file. Retry #" + (i + 1) + ": " + path);
Thread.Sleep(1000);
}
}
}
}
问题是这些函数有不同的签名,所以我不能使用委托将它们作为参数传递。有没有办法或模式可以帮我解决这个问题?
答案 0 :(得分:2)
请注意,这不使用委托,而是使用Func<T>
和Action
类型
我会将您的签名更改为:
public void CheckFunctionWithTrials(Action X)
这允许您传入一个不带参数且不返回任何内容的函数。然后,您可以使用匿名函数调用它,以“删除”参数。
CheckFunctionWithTrials(() => UploadFile(file));
这将使您的完整功能看起来像这样:
public void CheckFunctionWithTrials(Action X)
{
foreach (var i in Enumerable.Range(1, 5))
{
try
{
X?.Invoke();
break;
}
catch (Exception e)
{
if (i == 5)
{
throw;
}
else
{
//DLog.Warn("Failed to upload file. Retry #" + (i) + ": " + path);
Thread.Sleep(1000);
}
}
}
}
你也有一些函数的返回类型,为了让它工作,你需要泛型。
public T CheckFunctionWithTrials<T>(Func<T> X)
{
foreach (var i in Enumerable.Range(1, 5))
{
try
{
return X();
}
catch (Exception e)
{
if (i == 5)
{
throw;
}
else
{
//DLog.Warn("Failed to upload file. Retry #" + (i) + ": " + path);
Thread.Sleep(1000);
}
}
}
}
调用可能如下所示:
bool exists = CheckFunctionWithTrials(() => DirectoryExists(dir));
UPDATE:
我实际上在我的一个本地存储库中有一个类似的功能,它重试Task<T>
一次。相同的基本概念,就像async
方法
public async static Task<T> RetryOnceAsync<T>(this Func<Task<T>> tsk, TimeSpan wait)
{
try
{
return await tsk?.Invoke();
}
catch (Exception ex)
{
Logger.Error(ex.Message);
await Task.Delay(wait);
return await tsk?.Invoke();
}
}