AutoRest生成的客户端没有合适的构造函数,无法与services.AddHttpClient()方法一起使用。那么我们如何解决这个问题?
现在,我们有了带有此类签名的公共构造函数。
public Client(ServiceClientCredentials credentials, HttpClient httpClient, bool disposeHttpClient) : this(httpClient, disposeHttpClient)
但是因为它具有布尔disposeHttpClient参数,所以我们不能在AddHttpClient()方法中直接使用它来将客户端服务配置为DI。 令我深感遗憾的是,HttpClientFactory不包含带有这样签名的方法AddHttpClient的替代版本:
AddHttpClient<IClient>(Func<IServiceProvider, HttpClietn, IClient> configClient)
答案 0 :(得分:3)
您需要使用命名客户端,而不是类型客户端,然后您需要使用工厂重载来注册AutoRest客户端。
services.AddHttpClient("MyAutoRestClient", c =>
{
// configure your HttpClient instance
});
services.AddScoped<MyAutoRestClient>(p =>
{
var httpClient = p.GetRequiredService<IHttpClientFactory>().GetClient("MyAutoRestClient");
// get or create any other dependencies
// set disposeHttpClient to false, since it's owned by the service collection
return new MyAutoRestClient(credentials, httpClient, false);
});
答案 1 :(得分:0)
我建议比Chris Patt更优雅的解决方案。我们可以从生成的类继承并定义适用于DI和AddHttpClient()ctr的代码。请参见下面的代码。
public partial class MyAutoRestClientExtended: MyAutoRestClient
{
public MyAutoRestClientExtended(HttpClient httpClient, IOptions<SomeOptions> options)
: base(new EmptyServiceClientCredentials(), httpClient, false)
{
var optionsValue = options.Value ?? throw new ArgumentNullException(nameof(options));
BaseUri = optionsValue .Url;
}
}
现在,我们可以使用AddHttpClient()方法通过流利的方式构建器来配置类型化的客户端,该客户端具有其所有优点,例如Polly策略定义和HttpHandler定义。
services.AddHttpClient<MyAutoRestClientExtended>()
.ConfigureHttpClient((sp, httpClient) =>
{
httpClient.Timeout = TimeSpan.FromSeconds(30);
})
.SetHandlerLifetime(TimeSpan.FromMinutes(5))
.ConfigurePrimaryHttpMessageHandler(x => new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate })
.AddHttpMessageHandler(sp => sp.GetService<AuthenticationHandlerFactory>().CreateAuthHandler())
.AddPolicyHandlerFromRegistry(PollyPolicyName.HttpRetry)
.AddPolicyHandlerFromRegistry(PollyPolicyName.HttpCircuitBreaker);
并定义服务合同用法的单例服务。