繁体   English   中英

如何使用 HttpClient 处理数据提供者实例?

[英]How to dispose the data provider instance using HttpClient?

我已经使用存储库模式创建了我的数据提供者。

首先,我设计了一个基本存储库接口,如下所示:

internal interface IGenericRepository<T, in TResourceIdentifier>
{
    Task<IEnumerable<T>> GetManyAsync();
    Task<T> GetAsync(TResourceIdentifier id);
    Task PutAsync(T model);
    Task<T> PostAsync(T model);
    Task DeleteAsync(TResourceIdentifier id);
}

然后我实现了它:

public class GenericRepository<T, TResourceIdentifier> : IDisposable, IGenericRepository<T, TResourceIdentifier> 
    where T : class
{
    private bool _disposed;
    protected HttpClientHelper<T, TResourceIdentifier> Client;

    protected GenericRepository(string addressSuffix)
    {
        Client = new HttpClientHelper<T, TResourceIdentifier>(Properties.Settings.Url, addressSuffix);
    }

    public async Task<IEnumerable<T>> GetManyAsync()
    {
        return await Client.GetManyAsync();
    }

    // All other CRUD methods and dispose

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if(_disposed || !disposing) return;

        if(Client != null)
        {
            var mc = Client;
            Client = null;
            mc.Dispose();
        }

        _disposed = true;
    }
}

然后我为我的每个实体创建了自定义存储库接口。 例如:

internal interface IOrderRepository : IGenericRepository<Order, int>
{
    Task<IEnumerable<Order>> GetOrderBySomeConditionAsync(string condition );

}

最后,我实现了自定义存储库:

public class OrderRepository : GenericRepository<Order, int>, IOrderRepository
{
    public OrderRepository(string addressSuffix) : base(addressSuffix)
    {
    }

    public async Task<IEnumerable<Order>> GetOrderBySomeConditionAsync(string condition)
    {
        //get all the orders (GetManyAsync()) and then returns the ones meeting the condition
    }
}

注意HttpClientHelper使用HttpClient ,需要手动处理。

我创建了一个 MVC web 应用程序,并在 class 级别定义了存储库,如下所示:

IOrderRepository _orderRepository = new OrderRepository();

当我在 CRUD 操作中调用_orderRepository时,它在使用后不会命中 dispose。 为了解决这个问题,我最终实现了这样的:

private async Task<IEnumerable<OrderViewModel>> GetOrders()
{
    using(var orderRepository = new OrderRepository())
         return await orderRepository.GetManyAsync();
}

这会击中 Dispose 但是反模式。

我在我的实现中缺少什么实例没有在每次调用时处理?

您不应该在每次请求后处理 HTTPClient。

[ https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests][1]

正如上面的链接所说 -

因此,HttpClient 旨在被实例化一次并在应用程序的整个生命周期中重用。 为每个请求实例化一个 HttpClient class 将耗尽重负载下可用的 sockets 的数量。 该问题将导致 SocketException 错误。 解决该问题的可能方法是基于将 HttpClient object 创建为 singleton 或 static,如这篇关于 HttpClient 使用的 Microsoft 文章中所述。

在您的通用存储库中编写 Dispose 方法并不意味着它会在您觉得应该时自动调用。 它旨在单独调用,因此您必须使用using语句(如您所示)或代码中的Dispose方法。

或者,您可以将该工作留给垃圾收集器。

如果您确信使用GC.SuppressFinalize(this);

在此处阅读更多相关信息 - 我应该何时使用 GC.SuppressFinalize()?

正如R Jain指出的那样,您还应该创建一个 static class 来保存您的 HttpClient。 您必须根据需要使用 HttpResponseMessages 或 HttpContent。

更多阅读资源:

  1. 具有不同身份验证标头的 HttpClient 单个实例
  2. https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM