Frage

Ich versuche zur Zeit einige HttpWebRequest Funktionen zu ändern, aber ich kann es durch Vererbung nicht tun, weil HttpWebRequest keine öffentlichen Konstruktoren hat (neben dem Deserialisierungskonstruktor). Gibt es eine Abhilfe, dies zu tun?

Mein Ziel ist es unter so etwas wie das Beispiel zu codieren, aber diese Klasse Objekte müssen die HttpWebRequest Eigenschaften und Methoden erben:

using System;
using System.Net;
using System.Threading;

public class AsyncWebRequest:WebRequest
{
    private readonly AsyncCallback getResponseCallback;
    private readonly Uri uri;
    private volatile int RetriesLeft = 3;
    private volatile WebRequest request;

    public AsyncWebRequest(string uri, AsyncCallback getResponseCallback)
       :this(new Uri(uri), getResponseCallback)
    {
    }

    public AsyncWebRequest(Uri uri, AsyncCallback getResponseCallback):base()
    {
        this.uri = uri;
        this.getResponseCallback = getResponseCallback;
    }

    private IAsyncResult BeginGetResponse()
    {
        request = HttpWebRequest.CreateDefault(uri);
        ((HttpWebRequest)request).ReadWriteTimeout = Timeout;
        var result = request.BeginGetResponse(GetResponseCallback, null);
        ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle,
            GetResponseTimeout, null, Timeout, true);
        return result;
    }

    private void GetResponseTimeout(object state, bool timedOut)
    {
        if (timedOut)
        {
            Retry();
        }
    }

    private void Retry()
    {
        request.Abort();
        bool retry = false;
        lock (request)
        {
            if (RetriesLeft > 0)
            {
                Interlocked.Decrement(ref RetriesLeft);
                retry = true;
            }
        }
        if (retry)
        {
            BeginGetResponse();
        }
        else
        {
            getResponseCallback(null);
        }
    }

    private void GetResponseCallback(IAsyncResult AsyncResult)
    {
        try
        {
            getResponseCallback(AsyncResult);
        }
        catch(WebException webException)
        {
            Retry();
        }
    }
}
War es hilfreich?

Lösung

Wenn Sie die Serialisierung Konstruktor Trick können Sie Ihre Gebote zu tun, dann nein, es gibt keinen Weg.

Die Konstrukteure dieser Klasse sind intern, so dass Sie keine Möglichkeit haben, sie zu nennen.

Andere Tipps

Sie können nicht durch Vererbung von HttpWebRequest (wenn Sie nicht wollen, die Serialisierung Konstruktor aufzurufen), aber man kann durch Zusammensetzung und Delegation, und durch Vererbung von WebRequest (Ich bin nicht sicher, ob das tun wird es für Sie, aber funktionell ist es ganz ähnlich). WebRequest hat einen Standard-Konstruktor.

In diesem Fall können Sie dann nicht die Klasse haben ‚sein‘ ein HttpWebRequest (wie in eine ist-ein-Beziehung), da man nicht davon erstrecken kann, aber es wil ‚sein‘ ein WebRequest, das sollte ausreichen .

Sie können eine Klasse schreiben, die von WebRequest erbt, die eine Instanz Mitglied des Typs hat WebRequest, ein erstellen HttpWebRequest und im Konstruktor des neuen Typs und delegieren alle Anrufe an dieser Referenz (eine Art Dekorateur Muster Instanz Mitglied zuweisen ):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;

namespace ClassLibrary1
{
    public class MyHttpWebRequest : WebRequest
    {
        private WebRequest request;

        public MyHttpWebRequest(string uri)
        {
            request = HttpWebRequest.Create(uri);
        }

        public override WebResponse GetResponse()
        {
            // do your extras, or just delegate to get the original code, as long
            // as you still keep to expected behavior etc.
            return request.GetResponse();
        }

    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top