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

本文关键字:函数 参数 一个 构建 | 更新日期: 2023-09-27 18:09:30

我有一段非常难看的代码,它分散在整个项目中。这段代码的唯一不同之处在于其中一行调用了不同的方法。被调用的方法总是返回一个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;
            }
        }
    }
}

From repo

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

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

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

如果我理解你的目标,你就很接近了。你错过的最大的事情是将你的方法转换为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>

如果目标函数不需要任何参数,那么你可以按照其他答案中提到的那样做,只提供函数本身而不带括号。

我会签出Action<T>Func<T, TResult>委托。

  • 当你想传递一个void匿名方法时,使用Action<T>委托。

  • 当你需要传递一个带有返回类型的匿名方法时,使用Func<TResult>委托。

MSDN有一些很好的例子:

Func委派MSDN

动作委托MSDN

在我的职业生涯中,我多次使用过actions和function。当向不能重构的紧密耦合代码中添加特性时,它们会派上用场。

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