5

我正在尝试创建一个扩展 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 时,它不会在 Repository 中调用 SendAsync

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

我怎么做错了?我应该制作一个 HttpClientHandler 并将其包含在 HttpClient 中吗?如果这有任何不同,我已经尝试阅读有关虚拟的信息。但我不明白为什么它没有被调用。谁能帮我?

4

2 回答 2

11

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,而不是扩展它。(谷歌“组合与继承”了解更多信息)

于 2016-04-13T23:13:03.590 回答
-3

response = await base.SendAsync(request, cancelToken); 不返回任何东西只是永远等待,使用.configureawait(false)是一个好习惯吗?

于 2019-06-28T05:04:04.263 回答