简体   繁体   English

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

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

I have a very ugly piece of code that is scattered throughout a project. 我有一个非常丑陋的代码,分散在整个项目中。 The only difference in this piece of code is one line where a different method is called. 这段代码的唯一区别是一行调用了不同的方法。 The method that's called always returns a bool . 被调用的方法总是返回一个bool

I want to refactor this and extract it into its own method and pass the 1 liner into this method (if possible) from my understanding I can use a Func<> to do this. 我想重构它并将其提取到自己的方法中并将1个衬里传递给此方法(如果可能)从我的理解中我可以使用Func<>来执行此操作。

Here is what I am trying to do. 这是我想要做的。 I have tried to keep things as clear as possible 我尽力保持清晰

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 the repo 从回购

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

Does this make sense, am I on the right track, from the examples I have found they only show Funcs<> passing in a string or int which makes things look a whole lot simpler. 这是否有意义,我是在正确的轨道上,从我发现的例子中他们只显示Funcs<>传递一个stringint ,这使得事情看起来更加简单。

If I understand your goal, you're very close. 如果我了解你的目标,那你就非常接近了。 The biggest thing you're missing is the conversion of your method to a Func<> delegate. 您最不想要的是将方法转换为Func<>委托。 In your question, you included the argument parentheses. 在您的问题中,您包括参数括号。 You don't need these if you're not invoking the method. 如果您没有调用该方法,则不需要这些。

So, basically, this is what you probably want. 所以,基本上,这是你可能想要的。

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

Here is an example based on your provided details. 以下是基于您提供的详细信息的示例。

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;
}

The assumption here is that all the target methods will be returning Task<bool> 这里假设所有目标方法都将返回Task<bool>

If the target function does not require any parameters then you can do as mentioned in other answer and just provide the function itself without the parenthesis. 如果目标函数不需要任何参数,那么您可以按照其他答案中的说明进行操作,只提供没有括号的函数本身。

I would checkout Action<T> and Func<T, TResult> delegates. 我会结帐Action<T>Func<T, TResult>代表。

  • Use an Action<T> delegate when you wish to pass in an void anonymous method. 如果要传递void匿名方法,请使用Action<T>委托。

  • Use an Func<TResult> delegate when you need to pass in a anonymous method with a return type. 当需要传入带有返回类型的匿名方法时,请使用Func<TResult>委托。

MSDN has some good examples: MSDN有一些很好的例子:

Func Delegates MSDN Func代表MSDN

Action Delegates MSDN 操作代表MSDN

I have used actions and function many times over my career. 在我的职业生涯中,我多次使用过动作和功能。 They come in handy when adding features to tightly coupled code that cannot be refactored. 在为无法重构的紧密耦合代码添加功能时,它们会派上用场。

However, their correct usage should be used when writing loosely coupled code. 但是,在编写松散耦合的代码时,应该使用它们的正确用法。 There are many times where I wanted to give the implementer the option to provide their own functionality. 有很多次我想给实现者提供提供自己功能的选项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM