2013-03-30 53 views
2

我試圖創建一個擴展httpclient的類,但仍然是抽象的。擴展HttpClient

public abstract class Repository : HttpClient 
{ 
    public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     //retry logic here 
     var response = await base.SendAsync(request, cancellationToken); 
     while (!IsValid(response)) 
     { 
      Attempts++; 
      response = await Retry(request, cancellationToken); 
     } 
     Attempts = 0; 
     return response; 
    } 
    public int Attempts { get; set; } 
    public abstract bool IsValid(HttpResponseMessage response); 
    public abstract Task<HttpResponseMessage> Retry(HttpRequestMessage request, CancellationToken cancellationToken); 
    public abstract Type GetPageForUri(Uri uri); 
    public abstract Task<object> GetItems(Uri uri); 
} 

但是當一個子類調用getStringAsync它不會在存儲庫

public class EmailClient : Repository 
{ 
    public override bool IsValid(HttpResponseMessage response) 
    { 
     return response.IsSuccessStatusCode; 
    } 
    public override Task<HttpResponseMessage> Retry(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     return base.SendAsync(request, cancellationToken); 
    } 
    public override Type GetPageForUri(Uri uri) 
    { 
     return typeof(EmailPage); 
    } 
    public override async Task<object> GetItems(Uri uri) 
    { 
     var emails = await GetStringAsync(uri); 
     return emails; 
    } 
} 

調用SendAsync如何我究竟做錯了什麼?我應該製作一個HttpClientHandler並將它包含在HttpClient中嗎?我嘗試閱讀關於虛擬,如果這使得任何不同。但我不明白爲什麼它沒有被調用。誰能幫我?

+6

你爲什麼繼承'HttpClient'呢?這看起來像一個經典案例,其中構圖比繼承好得多。 –

+0

我希望其他人能夠使用'HttpClient'中的所有方法並進一步擴展這個類。 –

+0

您可以使用組合中的*類中的'HttpClient'中的所有方法。爲什麼會有人想將'EmailClient'或'Repository'視爲一個普通的'HttpClient'?他們不會*只想調用新引入的方法嗎? –

回答

4

HttpClient的是圍繞HttpMessageHandler實現(通常HttpClientHandler,這在大多數運行時實現所支持的功能特性)

實際上,有打算像您重試情景裝飾的HttpMessageHandler基類,DelegatingHandler,其中你可以瘦包裝實現這樣的:

喜歡的東西:

public class RetryMessageHandler : DelegatingHandler 
{ 
    readonly int retryCount; 

    public RetryMessageHandler(int retryCount) 
     : this(new HttpClientHandler(), retryCount) 
    { 
    } 

    public RetryMessageHandler(HttpMessageHandler innerHandler, int retryCount) 
     : base(innerHandler) 
    { 
     this.retryCount = retryCount; 
    } 

    public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     HttpResponseMessage response = null; 

     for (int i = 0; i<=retryCount; i++) 
     { 
      response = await base.SendAsync(request, cancellationToken); 

      if (response.IsSuccessStatusCode) 
      { 
       return response; 
      } 
     } 

     return response; 
    } 
} 

,你會再使用麗柯本:

HttpClient httpClient = HttpClientFactory.CreatePipeline(new HttpClientHandler(), 
    new [] { new RetryMessageHandler(3) }); 

var response = await httpClient.SendAsync(request); 

另外,我建議你EmailClient包裝/取決於HttpClient的,而不是擴展。 (關於爲什麼的更多信息,Google「Composition vs Inheritance」)