简体   繁体   English

如何使用 delegates/lambdas/Func<> 摆脱代码重用?

[英]How can I use delegates/lambdas/Func<> to get rid of code reuse?

I have a web service where I find myself putting the exact same try/catch block in every method and I'm trying to eliminate that code reuse.我有一个 web 服务,我发现自己在每个方法中都放置了完全相同的 try/catch 块,并且我试图消除代码重用。

Here is a sample method (some code removed) where you can see #1/#2/#3 are the core calls and are very similar.这是一个示例方法(删除了一些代码),您可以在其中看到#1/#2/#3 是核心调用并且非常相似。

    [HttpGet]
    [Route("GetKeys")]
    [Produces(MediaTypeNames.Application.Json)] // "application/json"
    public async Task<EntityKeyPage> GetKeys([FromQuery] string company = "", [FromQuery] DocumentPaging documentPaging = null)
    {
        [...]

        try
        {
            // Sometimes it's this #1
            VendTableServiceGetKeysResponse getKeysResponse = await aifClient.getKeysAsync(getKeysRequest);

            // Sometimes it's this #2
            // VendTableServiceReadResponse readResponse = await aifClient.readAsync(readRequest);

            // Sometimes it's this #3
            // VendTableServiceFindKeysResponse findKeysResponse = await aifClient.findKeysAsync(findKeysRequest);


        }
        catch (System.ServiceModel.FaultException<AifFault> ex)
        {
            var message = this.GetAXMessage(ex);

            aifClient.Abort();

            throw new Exception(message);
        }
        catch (Exception e)
        {
            aifClient.Abort();

            string errorMessage = e.Message != null ? e.Message : "";

            errorMessage = e.InnerException != null ? errorMessage + "\n" + e.InnerException : errorMessage;

            throw new Exception(errorMessage);
        }
        finally
        {
            aifClient.Close();
        }

        return getKeysResponse.EntityKeyPage;
    }

Here is my attempt at a generic method I can use.这是我可以使用的通用方法的尝试。

    private async Task<Out> MakeAIFCall<In, Out>(Func<In, Out> action, In @in)
    {
        Out @out;

        try
        {
            @out = action(@in);
        }
        catch (System.ServiceModel.FaultException<AifFault> ex)
        {
            var message = this.GetAXMessage(ex);

            aifClient.Abort();

            throw new Exception(message);
        }
        catch (Exception e)
        {
            aifClient.Abort();

            string errorMessage = e.Message != null ? e.Message : "";

            errorMessage = e.InnerException != null ? errorMessage + "\n" + e.InnerException : errorMessage;

            throw new Exception(errorMessage);
        }
        finally
        {
            aifClient.Close();
        }

        return @out;
    }

I wrote that method based on my reading, but I can't figure out how to call it?我根据阅读编写了该方法,但我不知道如何调用它? It appears I normally would pass a method name, but in this case it would be an object+method ( aifClient.getKeysAsync(...) / aifClient.readAsync(...) / aifClient.findKeysAsync(...) )?看来我通常会传递一个方法名称,但在这种情况下它将是一个对象+方法( aifClient.getKeysAsync(...) / aifClient.readAsync(...) / aifClient.findKeysAsync(...) )?

How do I call my method and or am I doing it wrong?我如何调用我的方法,或者我做错了什么?

This is my first attempt at calling it, but it's wrong:这是我第一次尝试调用它,但它是错误的:

var response = await MakeAIFCall<VendTableServiceGetChangedKeysRequest, VendTableServiceGetChangedKeysResponse>(aifClient.getKeysAsync, getKeysRequest);

The variables @out and @in were suggested by intellisense...I have no idea why the @ symbol is there or what it does.变量@out@in是由intellisense 建议的......我不知道为什么@符号在那里或它的作用。

Since your methods are awaited we can almost safely assume that they return tasks (however there are other possibilities), so first of all you will need to change your method signature to something like this:由于等待您的方法,我们几乎可以安全地假设它们返回任务(但是还有其他可能性),因此首先您需要将方法签名更改为如下所示:

private async Task<Out> MakeAIFCall<In, Out>(Func<In, Task<Out>> action, In @in)
{
    Out @out;

    try
    {
        @out = await action(@in);
    }
    ....

Second of all you can leverage existence of closures in C# so you will not need to provide a parameter:其次,您可以利用 C# 中存在的闭包,因此您无需提供参数:

private async Task<Out> MakeAIFCall<Out>(Func<Task<Out>> call)
{
    Out @out;

    try
    {
        @out = await call();
    }
    ....
}

And use it like that:并像这样使用它:

await MakeAIFCall(() => aifClient.getKeysAsync(getKeysRequest));

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

相关问题 如何利用委托来提高代码重用性? - How can I improve my code reuse by utilising delegates? 我可以在Action或Func委托中使用params吗? - Can I use params in Action or Func delegates? 代表,Lambdas,Action,Func,匿名函数 - Delegates, Lambdas, Action, Func, Anonymous Functions 当func &lt;&gt;的列表处理不同的对象时,如何接受Func &lt;&gt;委托的列表并返回列表的列表 - How can I accept a list of Func<> delegates and return a list of list when the List of func<> processes different objects 如何使用委托来处理文本? - How can I use delegates to process text? 如何在表达式内重用代码 <Func< … > &gt;? - How to reuse code inside a Expression<Func< … >>? 如何使用条件三元运算符在 lambda 之间有条件地分配 Func&lt;&gt;? - How can I assign a Func<> conditionally between lambdas using the conditional ternary operator? 如何摆脱这段代码中的反射调用? - How can I get rid of the reflection invoke in this piece of code? 我可以摆脱这个可怕的阻止代码吗? - Can I get rid of this horrible blocking code? 如何在Func委托列表上使用LINQ where子句 - How to use a LINQ where clause on a list of Func delegates
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM