由于HttpClient有释放连接的问题,在DotNetCore使用HttpClient请求数据的话建议使用HttpClientFactory。但是网上清一色的都是针对Asp.NetCore的资料。都是在Startup.cs里的ConfigureServices添加AddHttpClient服务,然后MVC里使用,如下:
services.AddHttpClient("webservice").ConfigurePrimaryHttpMessageHandler(() =>
{
return new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true,
};
});
但是我就不是用的MCV模式,或者我的dll里面要用HttpClient呢,就比较困扰了。我查看了AddHttpClient源码,里面确实有一堆依赖注入的环境,直接改源码的方式不可取。
细看发现他的本质都是把HttpClientFactory注入服务,然后用接口通过服务对象得到HttpClientFactory的单列实例。那么就有方式方便dll里使用了。包装如下:
项目中需要安装引用
Microsoft.Extensions.Http和Microsoft.Extensions.Hosting
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace liszlz
{
/// <summary>
/// HttpClientFactory工具类,简化得到HttpClientFactory
/// 使用如下
/// IHttpClientFactory factory = HttpClientFactoryUtil.GetFactory();
/// using (HttpClient client = factory.CreateClient("webservice"))
/// {
/// client.Timeout = new TimeSpan(1,0,0);
/// </summary>
class HttpClientFactoryUtil
{
/// <summary>
/// 服务
/// </summary>
private static IServiceProvider serviceProvider = null;
/// <summary>
/// 初始化服务,没给服务对象就自己创建
/// </summary>
/// <param name="provider">如果是asp.net可以直接抛过来ConfigureServices的services</param>
public static void InitService(IServiceProvider provider = null)
{
if (serviceProvider == null)
{
if (provider == null)
{
IHostBuilder builder = Host.CreateDefaultBuilder();
builder.ConfigureServices(services =>
{
services.AddHttpClient("webservice").ConfigurePrimaryHttpMessageHandler(() =>
{
return new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true,
};
});
});
serviceProvider = builder.Build().Services;
}
else
{
serviceProvider = provider;
}
}
}
/// <summary>
/// 得到IHttpClientFactory的对象
/// </summary>
/// <returns></returns>
public static IHttpClientFactory GetFactory()
{
if (serviceProvider == null)
{
InitService();
}
return serviceProvider.GetService<IHttpClientFactory>();
}
}
}
这样就得到一个简单易用的获取HttpClientFactory的工具类,Asp.NetCore用起来也容易,DLL用起来也容易。Asp.NetCore为了避免重复创建服务自己主动在Startup.cs里的ConfigureServices调用HttpClientFactoryUtil.InitService方法初始化服务。不初始化也行,就是重复创建了一个服务。
迷糊的问题回过头来再分析分析,发现本质了就好理解了。DotNet的很多服务都是依托依赖注入。依赖注入的本质就是个容器,供业务取注入的对象。而容器的操作句柄就是IServiceCollection services对象,所以控制台初始化的目的是为了得到IServiceCollection services对象。我们可以依赖这个对象往容器注入东西,也通过他从容器取东西。让业务缓存该对象就能绕开Asp.NetCore的通用MVC使用模式。也能对该对象进一步封装,更方便的使用容器,比如按配置文件注入类型。