模式/架构/匿名方法

时间:2012-12-29 10:39:28

标签: c#-4.0 design-patterns

我对C#比较陌生,也许你可以帮我解决这个问题。

我有几种调用某项服务的方法callServiceXY(param1, param2, ...)。由于许多原因,这些服务电话可能出错(我最终并不真正关心这个原因)。所以基本上我需要总是用这样的东西包装它们 - 如果出现问题就让它们再次执行:

var i = 3;
while(i>0)
  try{
   call...()
  } catch{
   i--;
  }
  i=0;
}

我宁愿只编写一次这段代码。我可以以某种方式有一个像tryXtimes(int x, callService())这样的方法,允许我执行一个未定义或匿名的方法吗? (我有Javascript记在哪里这可能......)?

3 个答案:

答案 0 :(得分:2)

是的,这是可能的。 C#3.5添加了对ActionFunc<T>类型的支持。 Action不会返回任何值,Func将始终返回一个值。

您有几个不同的版本也接受许多参数。以下控制台应用程序描述了如何执行此操作:

using System;

namespace Stackoverflow
{
    class Service
    {
        public int MyMethod() { return 42; }
        public void MyMethod(string param1, bool param2) { }

        public int MyMethod(object paramY) { return 42; }
    }

    class Program
    {
        static void ExecuteWithRetry(Action action)
        {
            try
            {
                action();
            }
            catch
            {
                action();
            }

        }

        static T ExecuteWithRetry<T>(Func<T> function)
        {
            try
            {
                return function();
            }
            catch
            {
                return function();
            }

        }

        static void Main(string[] args)
        { 
            Service s = new Service();
            ExecuteWithRetry(() => s.MyMethod("a", true));

            int a = ExecuteWithRetry(() => s.MyMethod(1));
            int b = ExecuteWithRetry(() => s.MyMethod(true));

        }
    }
}

如您所见,ExecuteWithRetry有两个重载。一个返回空白,一个返回一个类型。您可以通过传递ExecuteWithRetryAction来调用Func

- &GT;编辑:太棒了!只需要一些额外的代码来完成示例:

使用匿名函数/方法:

ExecuteWithRetry(() =>
{
   logger.Debug("test");
});

使用更多参数(action,int)

方法标题:

public static void ExecuteWithRetryX(Action a, int x)

方法调用:

ExecuteWithRetryX(() => { logger.Debug("test"); }, 2);

答案 1 :(得分:1)

我会使用策略/工厂模式。这个答案https://stackoverflow.com/a/13641801/626442给出了使用链接的策略/工厂模式的示例。上面链接中的问题将为您提供另一种可以采用此模式的示例。

这些设计模式有很多例子here,以下是Strategy patternFactory pattern的详细介绍。最后两个链接的前者还向您展示了如何将两者结合起来以执行您需要的操作。

我希望这会有所帮助。

答案 2 :(得分:0)

尝试以下

    void CallServiceXY(params object []objects)
    {
        Console.WriteLine("a");
        throw new Exception("");
    }

    void Retry(int maxRetryCount, Action<object[]> action, params object[] obj)
    {
        int retryCount = 1;
        while ( retryCount <= maxRetryCount)
        {
            try
            {

            action(obj);
            return;
            }
            catch
            {
                retryCount++;
            }
        }
    }

    void Main()
    {
        Retry(2,CallServiceXY);
        Retry(2,CallServiceXY,"");
        Retry(2,CallServiceXY,"","");

    }

演示here

Trick是Action<object[]>接受对象数组并在重试方法中返回void和params关键字。
要返回非空值,请将Action<object[]>更改为Func<T, object[]>