문제

나는 내 코드의 일부를 더 유창하게 만들려고 노력하고 있습니다.

문자열에서 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();

구문을 상당히 유창하게 유지하면서 내가하려는 일을하는 방법이 있습니까? 제안은 대단히 감사했습니다.

감사.

도움이 되었습니까?

해결책

확장 방법 또는 Lambda 표현식에는 메소드 그룹을 사용할 수 없습니다. 나 얼마 전에 이것에 대해 블로그를 작성했습니다.

나는 당신이 캐스팅 할 수 있다고 생각합니다 Func<string>:

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

그러나 그것은 꽤 불쾌합니다.

한 가지 대안은 변화하는 것입니다 Request() 에게 반품 기능 및 사용 :

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

또는 당신이 보관하고 싶다면 Request 메소드 자체는 단순하고 a를 추가하십시오 RequestFunc 방법:

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

그리고 전화 :

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

다른 팁

Why not turn this on its head?

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

What about enhancing the Request?

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

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

RequestOptions is a enum. You could also have more options, timeout arguments, number of retries etc.

OR

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

AFAIK you can write an extension method that extends a Func<T> delegate, but the compiler doesn't know what do you mean:

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

But if you explicitly cast the delegate will work:

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

The question here it whether the code readability is really improved in this case by an extension method.

I wouldn't write an extension method for string. Use a more specific type, like the Uri.

The full code:

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

Calling it:

 string html = new Uri("http://www.stackoverflow.com").Request().KeepTrying();
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top