委托签名/泛型委托?

3
我正在处理一个使用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个回答

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

谢谢,我现在使用的是C# 2,所以必须使用匿名方法而不是Lambda表达式,但这很有帮助。 - Charlie
好的,理论是一样的 ;-p - Marc Gravell

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接