Есть ли способ наследовать класс без конструкторов в .NET?

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

Вопрос

В настоящее время я пытаюсь изменить некоторые функции HttpWebRequest, но не могу сделать это посредством наследования, поскольку у HttpWebRequest нет общедоступных конструкторов (кроме конструктора десериализации).Есть ли обходной путь, чтобы сделать это?

Моя цель — написать что-то вроде примера ниже, но объекты этого класса должны наследовать свойства и методы 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();
        }
    }
}
Это было полезно?

Решение

Если вы не можете обмануть конструктор сериализации, чтобы он выполнил ваши приказы, тогда нет, никакого способа.

Конструкторы этого класса являются внутренними, поэтому у вас нет возможности их вызвать.

Другие советы

Вы не можете использовать наследование от HttpWebRequest (если вы не хотите вызывать конструктор сериализации), но вы можете использовать композицию и делегирование, а также наследование от WebRequest (я не уверен, подойдет ли это вам, но функционально очень похоже).WebRequest имеет конструктор по умолчанию.

В этом случае вы не можете сделать так, чтобы класс «был» HttpWebRequest (как в отношении is-a), поскольку вы не можете наследоваться от него, но он будет «быть» WebRequest, чего должно быть достаточно.

Вы можете написать класс, который наследуется от WebRequest, который имеет член экземпляра типа WebRequest, создать HttpWebRequest и присвоить его члену экземпляра в конструкторе нового типа и делегировать все вызовы этой ссылке (что-то вроде шаблона декоратора):

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

    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top