Existe alguma maneira para herdar uma classe sem construtores em .NET?
-
03-07-2019 - |
Pergunta
Atualmente estou tentando modificar algumas funções HttpWebRequest, mas não posso fazê-lo através de herança, porque HttpWebRequest não tem construtores públicos (além do construtor desserialização). Existe uma solução para isso?
O meu objectivo é código algo como o exemplo a seguir, mas esta classe objetos devem herdar as HttpWebRequest propriedades e métodos:
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();
}
}
}
Solução
A menos que você pode enganar o construtor de serialização para fazer o seu lance, então não, não há nenhuma maneira.
Os construtores dessa classe são internos, de modo que você não tem nenhuma maneira de chamá-los.
Outras dicas
Você não pode através de herança de HttpWebRequest (se você não quer chamar o construtor de serialização), mas você pode através composição e delegação, e através da herança de WebRequest (Eu não tenho certeza se isso vai fazê-lo para você, mas funcionalmente é bastante similar). WebRequest tem um construtor padrão.
Neste caso, você pode, então, não tem a classe 'ser' um HttpWebRequest (como em uma relação é-um), desde que você não pode estender a partir dele, mas ele wil 'ser' um WebRequest, que deve ser suficiente .
Você poderia escrever uma classe que herda de WebRequest, que tem um membro de instância do tipo WebRequest, criar um HttpWebRequest e atribuir-membro de instância no construtor do novo tipo e delegar todas as chamadas para que a referência (uma espécie de padrão Decorator ):
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();
}
}
}