没有找到合适的类型构造函数

A suitable constructor of type does not be located

我正在尝试最简单的IHttpClientFactory用例

public interface IWeatherForecast
{
    Task<string> Get();
}

class WeatherForecast : IWeatherForecast
{
    private readonly HttpClient httpClient;
    public WeatherForecast (IHttpClientFactory httpClientFactory)
    {
        httpClient = httpClientFactory.CreateClient();
    }
    public async Task<string> Get()
    {
        var resp = await httpClient.GetAsync("https://testwebapiforuseinsamples.azurewebsites.net/weatherforecast");
        return JsonConvert.SerializeObject(resp.Content.ReadAsStringAsync());
    }
}

然后实例化它

static async Task Main(string[] args)
{
    var container = new ServiceCollection();
    container.AddHttpClient<IWeatherForecast, WeatherForecast>();
    var serviceProvider = container.BuildServiceProvider();    
    var resp = await serviceProvider.GetRequiredService<WeatherForecast>().Get();
}

然而当我运行它时,它抛出

System.InvalidOperationException: 'A suitable constructor for type 'HttpClientFactoryExample.WeatherForecast' could not be located. Ensure the type is concrete ...

谁能指出这段代码有什么问题。我期望在向 DI 添加 WeatherForecast 服务后,我将能够从容器中获取它的初始化实例。

当使用像您在此处所做的那样进行抽象的类型客户端注册时

//...

container.AddHttpClient<IWeatherForecast, WeatherForecast>();

//...

它将抽象注册为客户端类型,而不是实现。

Adds the IHttpClientFactory and related services to the IServiceCollection and configures a binding between the TClient type and a named HttpClient. The client name will be set to the type name of TClient.

引用IHttpClientBuilder AddHttpClient<TClient,TImplementation>

因为你尝试解析实现WeatherForecast

//...

var resp = await serviceProvider.GetRequiredService<WeatherForecast>().Get();

//...

它会失败,因为

System.InvalidOperationException: No service for type 'WeatherForecast' has been registered.

你应该真正解决的是抽象IWeatherForecast

//...

var resp = await serviceProvider.GetRequiredService<IWeatherForecast>().Get();

//...

容器知道映射到 WeatherForecast 实现,然后将其及其依赖项一起初始化。

解决了这个问题后,您还需要更新服务以显式依赖 HttpClient,因为这是类型化的客户端注册

class WeatherForecast : IWeatherForecast {
    private readonly HttpClient httpClient;

    public WeatherForecast (HttpClient httpClient) {
        this.httpClient = httpClient;
    }

    public async Task<string> Get() {
        var resp = await httpClient.GetAsync("https://testwebapiforuseinsamples.azurewebsites.net/weatherforecast");
        return JsonConvert.SerializeObject(resp.Content.ReadAsStringAsync());
    }
}

引用Use IHttpClientFactory to implement resilient HTTP requests

当您在服务集合中将类型注册为 HTTP 客户端 container.AddHttpClient<IWeatherForecast, WeatherForecast>() 时,它必须在构造函数中包含 HttpClient。在你的情况下应该是:

public WeatherForecast(HttpClient httpClient)
{
     this.httpClient = httpClient;
}

另一种选择是分别注册 HttpClientFactory 和您的 WeatherForecast 服务:

container.AddHttpClient();
container.AddTransient<IWeatherForecast, WeatherForecast>();

然后将服务与 HttpClientFactory 一起使用:

private readonly HttpClient httpClient;

public WeatherForecast(IHttpClientFactory factory)
{
    this.httpClient = factory.CreateClient();
}