Question

J'essaie de rendre une partie de mon code plus fluide.

J'ai une extension de chaîne qui crée une requête HTTP à partir de la chaîne et renvoie la réponse sous forme de chaîne. Donc, je peux faire quelque chose comme ...

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

J'essaie d'écrire une extension qui continuera d'essayer la demande jusqu'à ce qu'elle réussisse. Ma signature ressemble à quelque chose comme ...

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
}

J'ai l'intention d'appeler ça quelque chose comme ...

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

Hélas, cela ne semble pas fonctionner =). J'ai d'abord essayé d'en faire un lambda, mais cela ne semble pas fonctionner non plus.

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

Existe-t-il un moyen de faire ce que j'essaie de faire tout en maintenant la syntaxe assez fluide?  Suggestions très appréciées.

Merci.

Était-ce utile?

La solution

Vous ne pouvez pas utiliser un groupe de méthodes pour les méthodes d'extension ou les expressions lambda. Je a blogué à ce sujet il y a quelque temps .

J'imagine que vous pourriez transtyper vers Func < chaîne > :

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

mais c'est assez méchant.

Une alternative serait de remplacer Request () par renvoyer un Func et utiliser:

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

Ou si vous souhaitez conserver la méthode Request elle-même simple, ajoutez simplement une méthode RequestFunc :

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

puis appelez:

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

Autres conseils

Pourquoi ne pas renverser la situation?

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

Qu'en est-il de l'amélioration de la demande?

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

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

RequestOptions est une énumération. Vous pouvez également disposer de davantage d'options, d'arguments de délai d'expiration, de nombre de tentatives, etc.

.

OU

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

autant que je sache, vous pouvez écrire une méthode d'extension qui étend un délégué Func < T > , mais le compilateur ne sait pas ce que vous voulez dire:

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

Mais si vous lancez explicitement le délégué, cela fonctionnera:

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

La question ici est de savoir si la lisibilité du code est vraiment améliorée dans ce cas par une méthode d'extension.

Je n'écrirais pas de méthode d'extension pour string. Utilisez un type plus spécifique, tel que Uri .

Le code complet:

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

L'appeler:

 string html = new Uri("http://www.stackoverflow.com").Request().KeepTrying();
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top