我有一大堆代码在一个中等复杂的重试和try / catch逻辑中执行“文件放置”操作。这工作正常,看起来大致如下:
while (...) {
try {
FilePut(source, destination)
}
catch () {
//Check exception type, possibly re-throw, possibly return, possibly increment
//counters being checked by while loop
}
}
这种逻辑的细节不是问题。但我意识到我还有其他一些操作也需要在同一种逻辑中执行,我想避免复制并在我的应用程序中粘贴这个逻辑。我想将它移动到一个函数并重用该函数。该函数必须对要调用的操作进行某种引用,try逻辑将执行该操作(文件put,文件get,等等)。
对于委托来说,这似乎是个好地方,但问题是,每个操作都有不同的签名,所以我不知道如何能够编写上面的逻辑来调用“any”操作
在C#中有一个很好的方法吗?
答案 0 :(得分:4)
您需要Action
delegate来隐藏所有不同的签名。像这样:
public void DoAction(Action action)
{
// Make the boilerplate code whatever you need it to be.
// I've just used a try catch for simplicity.
try
{
// Call the action at the appropriate time.
action();
}
catch
{
// Handle any exceptions as you wish.
}
}
然后,为了能够处理具有不同签名的操作,您可以定义一些重载,这些重载采用不同类型的通用Action<T>
委托和所有必需的参数。这些重载会将通用操作及其参数“curry”到普通Action
:
public void DoAction<T>(Action<T> action, T arg1)
{
DoAction(() => action(arg1));
}
public void DoAction<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2)
{
DoAction(() => action(arg1, arg2));
}
public void DoAction<T1, T2, T3>(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3)
{
DoAction(() => action(arg1, arg2, arg3));
}
// etc...
使用:
public void SomeOtherMethod()
{
DoAction(MethodThatTakesTwoInts, 42, 23);
DoAction(MethodThatTakesAString, "Don't Panic!");
}
此外,如果您不熟悉它们,请查看Func
delegates的相关系列以及其他方法。
答案 1 :(得分:0)
您可以使用递归:
protected void TryNTimes(int numberOfTries, Action action)
{
try
{
if (numberOfTries == 0) return;
action();
}
catch (Exception)
{
TryNTimes(numberOfTries - 1, action);
}
}
然后像这样使用它:
TryNTimes(10, () => Foo());