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

残念ながら、それはうまくいかないようです =)。最初にラムダにしようとしましたが、それもうまくいかないようです。

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

構文をかなり流暢に保ちながら、私がやろうとしていることを行う方法はありますか? 提案は大歓迎です。

ありがとう。

4

5 に答える 5

4

拡張メソッドまたはラムダ式にメソッド グループを使用することはできません。私はこれについて少し前にブログを書きました。

にキャストできると思いますFunc<string>

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

しかし、それはかなり厄介です。

1 つの代替方法は、FuncRequest()返すように変更して、次を使用することです。

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

文字列の拡張メソッドは記述しません。のような、より具体的なタイプを使用します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 に答える
0

私の知る限り、デリゲートを拡張する拡張メソッドを作成できます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 に答える