الحصول على طريقة parameterless أن يتصرف مثل ظائفها <العودة>

StackOverflow https://stackoverflow.com/questions/801060

سؤال

وأنا أحاول أن تجعل جزءا من قانون بلدي أكثر طلاقة.

ولدي تمديد سلسلة يجعل طلب 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();

هل هناك طريقة لفعل ما أحاول القيام به مع الحفاظ على جملة بطلاقة إلى حد ما؟  الاقتراحات محل تقدير كبير.

وشكرا.

هل كانت مفيدة؟

المحلول

ولا يمكنك استخدام مجموعة طريقة لطرق الإرشاد، أو تعبيرات لامدا. I <لأ href = "http://msmvps.com/blogs/jon_skeet/archive/2008/01/08/extension-methods-on-lamdba-expressions-don-t-work-unfortunately.aspx" يختلط = "نوفولو noreferrer "> كتبت عن هذا منذ فترة .

وأظن هل يمكن أن يلقي لFunc<string>:

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

ولكن هذا مقرف جدا.

وبديل واحد سيكون لتغيير Request() إلى <م> عودة وظائفها، والاستخدام:

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

نصائح أخرى

لماذا لا يتحول هذا رأسا على عقب؟

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

وماذا عن تعزيز طلب؟

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

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

وRequestOptions هو التعداد. هل يمكن أن يكون أيضا المزيد من الخيارات، والحجج مهلة، وعدد من المحاولات وغيرها.

و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 يمكنك كتابة طريقة التمديد الذي يمتد مندوب Func<T>، ولكن المترجم لا يعرف ماذا تقصد:

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

ولكن إذا كنت يلقي صراحة مندوب ستعمل:

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

والسؤال هنا هو ما إذا كان تحسن قراءة كود حقا في هذه الحالة باستخدام أسلوب التمديد.

وأنا لن كتابة طريقة التمديد لسلسلة. استخدام نوع أكثر تحديدا، مثل 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();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top