Question

J'essaie actuellement de modifier certaines fonctions HttpWebRequest, mais je ne peux pas le faire par héritage, car HttpWebRequest n'a pas de constructeur public (à part le constructeur de désérialisation). Existe-t-il une solution de contournement pour cela?

Mon objectif est de coder quelque chose comme l'exemple ci-dessous, mais ces objets de classe doivent hériter des propriétés et méthodes 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();
        }
    }
}
Était-ce utile?

La solution

Sauf si vous pouvez tromper le constructeur de la sérialisation pour répondre à vos demandes, alors non, il n'y a pas moyen.

Les constructeurs de cette classe sont internes, vous n'avez donc aucun moyen de les appeler.

Autres conseils

Vous ne pouvez pas utiliser l'héritage de HttpWebRequest (si vous ne souhaitez pas appeler le constructeur de la sérialisation), mais vous pouvez utiliser la composition et la délégation, ainsi que l'héritage de WebRequest (je ne sais pas si cela le fera pour vous, mais fonctionnellement c'est assez semblable). WebRequest a un constructeur par défaut.

Dans ce cas, vous ne pouvez pas avoir la classe "être" une requête HttpWebRequest (comme dans une relation is-a), car vous ne pouvez pas l'étendre, mais il s'agira d'une "requête Web", ce qui devrait suffire .

Vous pouvez écrire une classe qui hérite de WebRequest, qui a un membre d'instance de type WebRequest, créer un HttpWebRequest et affecter un membre d'instance dans le constructeur du nouveau type et déléguer tous les appels à cette référence (sorte de modèle de décorateur). ):

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

    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top