2

我正在尝试使我的代码的一部分更加流畅。

我有一个字符串扩展,它从字符串发出 HTTP 请求并将响应作为字符串返回。所以我可以做类似的事情......

string _html = "http://www.stackoverflow.com".Request();

我正在尝试编写一个扩展,它将继续尝试请求直到它成功。我的签名看起来像...

public static T KeepTrying<T>(this Func<T> KeepTryingThis) {
  // Code to ignore exceptions and keep trying goes here
  // Returns the result of KeepTryingThis if it succeeds
}

我打算称它为...

string _html = "http://www.stackoverflow.com".Request.KeepTrying();

唉,这似乎不起作用=)。我试着先把它变成一个 lambda,但这似乎也不起作用。

string _html = (() => "http://www.stackoverflow.com".Request()).KeepTrying();

有没有办法在保持语法相当流畅的同时做我想做的事情?建议非常感谢。

谢谢。

4

5 回答 5

4

您不能将方法组用于扩展方法或 lambda 表达式。我不久前在博客上写过这个

我怀疑你可以投到Func<string>

string _html = ((Func<string>)"http://www.stackoverflow.com".Request)
                    .KeepTrying();

但这很讨厌。

一种替代方法是更改Request()​​为返回Func,并使用:

string _html = "http://www.stackoverflow.com".Request().KeepTrying();

或者,如果您想保持Request方法本身简单,只需添加一个RequestFunc方法:

public static Func<string> RequestFunc(this string url)
{
    return () => url.Request();
}

然后调用:

string _html = "http://www.stackoverflow.com".RequestFunc().KeepTrying();
于 2009-04-29T06:05:51.060 回答
3

为什么不把它转过来呢?

  static T KeepTrying<T>(Func<T> func) {
        T val = default(T);
        while (true) {
            try {
                val = func();
                break;
            } catch { }
        }

        return val;
    }

    var html = KeepTrying(() => "http://www.stackoverflow.com".Request());
于 2009-04-29T06:16:57.227 回答
1

那么增强请求呢?

string _html = "http://www.stackoverflow.com".Request(RequestOptions.KeepTrying);

string _html = "http://www.stackoverflow.com".Request(RequestOptions.Once);

RequestOptions是一个枚举。您还可以有更多选项、超时参数、重试次数等。

或者

public static string RepeatingRequest(this string url) {
  string response = null;
  while ( response != null /* how ever */ ) {
    response = url.Request();
  }
  return response;
}

string _html = "http://www.stackoverflow.com".RepeatingRequest();
于 2009-04-29T06:48:24.283 回答
0

AFAIK您可以编写扩展Func<T>委托的扩展方法,但编译器不知道您的意思是什么:

string _html = "http://www.stackoverflow.com".Request.KeepTrying(); // won't work

但是,如果您明确地强制转换委托将起作用:

string _html = ((Func<string>)"http://www.stackoverflow.com".Request).KeepTrying(); // works

这里的问题是,在这种情况下,通过扩展方法是否真的提高了代码的可读性。

于 2009-04-29T07:23:23.713 回答
0

我不会为字符串编写扩展方法。使用更具体的类型,例如Uri.

完整代码:

public static class Extensions
{
    public static UriRequest Request(this Uri uri)
    {
        return new UriRequest(uri);
    }

    public static UriRequest KeepTrying(this UriRequest uriRequest)
    {
        uriRequest.KeepTrying = true;
        return uriRequest;
    }
}

public class UriRequest
{
    public Uri Uri { get; set; }
    public bool KeepTrying { get; set; }
    public UriRequest(Uri uri)
    {
        this.Uri = uri;
    }

    public string ToHtml()
    {
        var client = new System.Net.WebClient();

        do
        {
            try
            {
                using (var reader = new StreamReader(client.OpenRead(this.Uri)))
                {
                    return reader.ReadToEnd();
                }
            }
            catch (WebException ex)
            {
                // log ex
            }
        }
        while (KeepTrying);

        return null;
    }

    public static implicit operator string(UriRequest uriRequest)
    {
        return uriRequest.ToHtml();
    }    
}

调用它:

 string html = new Uri("http://www.stackoverflow.com").Request().KeepTrying();
于 2009-04-29T11:06:41.370 回答