构建允许将函数作为参数传入的通用 c# 函数

Building a generic c# function that allows a function to be passed in as a parameter

我有一段非常难看的代码散布在整个项目中。这段代码的唯一区别是调用不同方法的一行。调用的方法总是 returns a bool.

我想重构它并将它提取到它自己的方法中,并将 1 衬里传递到这个方法中(如果可能的话)根据我的理解我可以使用 Func<> 来做到这一点。

这就是我想要做的。我尽量把事情说清楚

public async Task<bool> SomeMethod()
{
    //code removed for readability.

    //IsCustomerComplete will return a bool
    var process =  await RepeatableMasterPiece(1, 2, _myRepo.IsCustomerComplete(someParameterRequired));

    //do something with process result
    return process;
}

private async Task<bool> RepeatableMasterPiece(int param1, int param2, Func<Task<bool>> method)
{
    int retry = 0;
    bool soapComplete = false;
    string soapFault = "just a placeholder for example";
    bool blackListStatus = false;
    while (!soapComplete && retry <= 1)
    {
        try
        {
            if (soapFault != null)
            {
                //do some stuff with param1 & param2 here
            }
            if (!soapComplete)
            {
                return await method.Invoke();
            }
        }
        catch (FaultException ex)
        {
            soapFault = ex.Message;
            retry++;
            if (retry > 1)
            {
                throw ex;
            }
        }
    }
}

来自代码库

public async Task<bool> IsCustomerComplete(int id)
{
    ...removed other code here
    return true;
}

这有意义吗,我在正确的轨道上吗,从我发现的例子中他们只显示 Funcs<> 传递 stringint 这让事情看起来简单多了。

我会检查 Action<T>Func<T, TResult> 代表。

  • 当您希望传入无效的匿名方法时,请使用 Action<T> 委托。

  • 当您需要传入具有 return 类型的匿名方法时,请使用 Func<TResult> 委托。

MSDN 有一些很好的例子:

Func Delegates MSDN

Action Delegates MSDN

在我的职业生涯中,我多次使用动作和函数。在向无法重构的紧密耦合代码添加功能时,它们会派上用场。

但是,在编写松散耦合的代码时应该使用它们的正确用法。有很多次我想让实施者选择提供他们自己的功能。

如果我了解您的目标,那么您就非常接近了。您缺少的最重要的事情是将您的方法转换为 Func<> 委托。在您的问题中,您包含了参数括号。如果您不调用该方法,则不需要这些。

所以,基本上,这就是您可能想要的。

 var process =  await RepeatableMasterPiece(1, 2, _myRepo.IsCustomerComplete);

这是一个基于您提供的详细信息的示例。

public async Task SomeMethod() {
    //code in method.

    var _myRepo = new repo();
    var someParameterRequired = 1;
    var process = await RepeatableMasterPiece(1, 2, () => _myRepo.IsCustomerComplete(someParameterRequired));

    //do something with process result
}

private async Task<bool> RepeatableMasterPiece(int param1, int param2, Func<Task<bool>> method) {
    int retry = 0;
    bool soapComplete = false;
    string soapFault = "just a placeholder for example";
    bool blackListStatus = false;
    while (!soapComplete && retry <= 1) {
        try {
            if (soapFault != null) {
                //do some stuff with param1 & param2 here
            }
            if (!soapComplete && method != null) {
                return await method();
            }
        } catch (FaultException ex) {
            soapFault = ex.Message;
            retry++;
            if (retry > 1) {
                throw ex;
            }
        }
    }
    return false;
}

这里假设所有目标方法都将返回 Task<bool>

如果目标函数不需要任何参数,那么您可以按照其他答案中的说明进行操作,只需提供不带括号的函数本身。