7

我正在 csharp (.net 4.0) 中构建一个消息传递应用程序,我的班级有发送/接收消息的基本方法:

void sendMessage( string msgBody, string properties);
object getNextMessage();
object getMessageById( string msgId);

这些方法中的每一种都依赖于底层连接;如果连接过时,我会使用 try/catch 和一些重试逻辑来进行额外的尝试,如下所示:

public object getNextMessage(){
   object nextMessage = null;
   int retryAttempts = 0;
   int MAX_ATTEMPTS = 3;

   while( retryAttempts < MAX_ATTEMPTS){
      retryAttempts++;
      try{
         nextMessage = connection.getMessage("queueName");
      }catch(Exception e){   
      }
   }
   return nextMessage;
}

由于重试逻辑是通用的,我想避免在每个方法中重复相同的代码。我想创建一个通用的重试函数并执行以下操作:

public object makeAttempt( CodeBlock codeBlock){
       while( retryAttempts < MAX_ATTEMPTS){
          retryAttempts++;
          try{
             return codeBlock.invoke()
          }catch(Exception e){   
          }
       }
       return null;
}

..我想这样使用makeAttempt,或者类似的东西:

public object getNextMessage(){       
   makeAttempt() => {
      return connection.getMessage("queueName");
   }
}

我对此进行了审查但它涉及将整个函数作为参数传递,我没有这样做。我还查看了.net Lambda Expressions,但我没有看到连接。

我没有做太多 C# 所以请原谅 n00b 问题:-)

4

1 回答 1

11

你快到最后了——你只需要把 lambda 表达式括起来,()因为它是一个方法参数。您还需要使用 frommakeAttempt的返回值来为您的getNextMessage方法提供返回值。所以:

public object getNextMessage(){       
   return makeAttempt(() => {
      return connection.getMessage("queueName");
   });
}

或者更简单地说,使用表达式 lambda:

public object getNextMessage(){       
   return makeAttempt(() => connection.getMessage("queueName"));
}

这都是假设这CodeBlock是一个委托类型,当然,例如

public delegate object CodeBlock();

您还需要更改makeAttempt为调用Invoke而不是invoke- C# 区分大小写。我强烈建议您也遵循 .NET 命名约定,其中方法PascalCased不是camelCased.

编辑:如评论中所述,您可以将其设为通用:

public T CallWithRetries<T>(Func<T> function)
{
    for (int attempt = 1; attempt <= MaxAttempts; attempt++)
    {
        try
        {
            return function();
        }
        catch(Exception e)
        {
            // TODO: Logging
        }
    }
    // TODO: Consider throwing AggregateException here
    return default(T);
}
于 2013-10-17T17:02:04.303 回答