委托签名/通用代表?

时间:2009-06-15 10:21:30

标签: c# .net

我正在开发一个使用Windows Mobile设备调用Web服务的项目。

要求说明如果服务调用失败,则应提示用户重试。目前,有一个服务代理调用Web服务代理上的所有方法,如果调用失败,则会有一些代码提示用户重试,然后再次调用该调用。它看起来像这样:

public void MyServiceCall(string stringArg, bool boolArg, int intArg)
{
    try
    {
        MyWebService.MyServiceCall(stringArg, boolArg, intArg);
    }
    catch(SoapException ex)
    {
        bool retry = //a load of horrid code to prompt the user to retry
        if (retry)
        {
            this.MyServiceCall(stringArg, boolArg, intArg);
        }
    }
}

catch中的东西在系统上看起来比在该片段中看起来更麻烦,并且CTRL-C CTRL-V模式已被用于在每个服务调用中复制它。我想将这个重复的代码重构为一个方法,但我不确定重试方法调用的最佳方法。我正在考虑让一个委托作为我的新方法的参数,但由于我不知道签名,我不确定如何以通用方式执行此操作。有人可以帮忙吗?感谢。

2 个答案:

答案 0 :(得分:7)

我认为你只需要两种方法:

protected void Invoke(Action action) {
    try {
       action();
    } catch {...} // your long boilerplate code
}
protected T Invoke<T>(Func<T> func) {
    try {
       return func();
    } catch {...} // your long boilerplate code
}

然后你可以使用:

public void MyServiceCall(string stringArg, bool boolArg, int intArg)
{
    Invoke(() => MyWebService.MyServiceCall(stringArg, boolArg, intArg));
}

同样使用其他版本的方法返回值。如果需要,您还可以让代理人将服务本身作为参数 - 这可能因IDisposable原因而有用:

protected void Invoke(Action<MyService> action) {
   using(MyService svc = new MyService()) {
     try {
       action(svc);
     } catch {...} // your long boilerplate code
   }
}
...
public void MyServiceCall(string stringArg, bool boolArg, int intArg)
{
    Invoke(svc => svc.MyServiceCall(stringArg, boolArg, intArg));
}

答案 1 :(得分:2)

只需在我的脑海中编写代码......你也可以为Func实现类似的东西来返回值。

public static void ExecuteServiceCall(Action serviceCall) {
    while (true) {
        try {
            serviceCall();
            return;
        } catch (SoapException ex) {
            bool retry = // whaazzaaaaa!?
            if (!retry)
                // Dont retry, but fail miserably. Or return. Or something.
                throw;
        }
    }
}

public void MyServiceCall(string stringArg, bool boolArg, int intArg) {
    ExecuteServiceCall(() => MyWebService.MyServiceCall(stringArg, boolArg, intArg));
}