如何包装函数及其参数......有点像“超级委托”?

Mic*_*ett 5 c# delegates

我有一段代码,在一段中等复杂的重试和 try/catch 逻辑中执行“文件放置”操作。这工作正常,它看起来大致是这样的:

while (...) {
try {
    FilePut(source, destination)
    }
catch () {
   //Check exception type, possibly re-throw, possibly return, possibly increment
   //counters being checked by while loop
   }
}
Run Code Online (Sandbox Code Playgroud)

这个逻辑的细节不是问题。但我意识到我还有其他几个操作也需要在这种相同类型的逻辑中执行,并且我希望避免在我的应用程序中复制和粘贴此逻辑。我想将其移至一个函数并重用该函数。该函数必须对要调用的操作进行某种引用,并且 try 逻辑将执行该操作(文件放入、文件获取等)。

这对于委托来说似乎是一个好地方,但问题是,每个操作都有不同的签名,所以我不确定如何编写上面的逻辑以便能够调用“任何”操作。

在 C# 中有没有好的方法可以做到这一点?

Fis*_*rdo 6

您需要一个Action委托来隐藏所有不同的签名。像这样的东西:

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.
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,为了能够处理具有不同签名的操作,您可以定义一些重载,这些重载采用不同类型的通用Action<T>委托和所有必要的参数。这些重载会将通用操作及其参数“柯里化”为普通的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...
Run Code Online (Sandbox Code Playgroud)

使用方法:

public void SomeOtherMethod()
{
    DoAction(MethodThatTakesTwoInts, 42, 23);
    DoAction(MethodThatTakesAString, "Don't Panic!");
}
Run Code Online (Sandbox Code Playgroud)

另外,如果您不熟悉他们,也可以看看Func代表的相关家族。