Domanda

Attualmente sto cercando di modificare alcune funzioni di HttpWebRequest, ma non posso farlo tramite l'ereditarietà perché HttpWebRequest non ha costruttori pubblici (oltre al costruttore di deserializzazione). C'è una soluzione alternativa per farlo?

Il mio obiettivo è codificare qualcosa come nell'esempio seguente, ma gli oggetti di questa classe devono ereditare le proprietà e i metodi HttpWebRequest:

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();
        }
    }
}
È stato utile?

Soluzione

A meno che tu non possa ingannare il costruttore della serializzazione per fare le tue offerte, allora no, non c'è modo.

I costruttori di quella classe sono interni, quindi non hai modo di chiamarli.

Altri suggerimenti

Non è possibile tramite l'ereditarietà da HttpWebRequest (se non si desidera chiamare il costruttore della serializzazione), ma è possibile tramite la composizione e la delega e tramite l'eredità da WebRequest (non sono sicuro che lo farà per tu, ma funzionalmente è abbastanza simile). WebRequest ha un costruttore predefinito.

In questo caso non puoi avere la classe 'be' un HttpWebRequest (come in una relazione is-a), dal momento che non puoi estenderlo, ma sarà 'essere' una WebRequest, che dovrebbe essere sufficiente .

Potresti scrivere una classe che eredita da WebRequest, che ha un membro di istanza di tipo WebRequest, creare un HttpWebRequest e assegnare al membro di istanza nel costruttore del nuovo tipo e delegare tutte le chiamate a quel riferimento (tipo di modello di decoratore ):

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

    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top