System.InvalidOperationException:找不到类型“X”的合适构造函数。确保类型是具体的,并且公共构造函数的所有参数都注册为服务或作为参数传递。还要确保没有提供无关的参数。
如何解决?这很容易。但首先,让我向您展示我在错误版本中做了什么。
对于此示例,我创建了一个基本项目。
这是一个 .NET 7 API 项目,只有一个控制器,它调用接口中定义的另一个服务。GenderController
IGenderizeService
public interface IGenderizeService { Task<GenderProbability> GetGenderProbabiliy(string name); }
IGenderizeService
由一个类实现,该类是加载失败的类,因此会导致引发异常。该类调用外部终结点,分析结果,然后将其返回给调用方:GenderizeService
public class GenderizeService : IGenderizeService { private readonly IHttpClientFactory _httpClientFactory; public GenderizeService(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } public async Task<GenderProbability> GetGenderProbabiliy(string name) { var httpClient = _httpClientFactory.CreateClient(); var response = await httpClient.GetAsync($"?name={name}"); var result = await response.Content.ReadFromJsonAsync<GenderProbability>(); return result; } }
最后,我在 Program 类中定义了服务,然后指定了哪个是在类中生成的 HttpClient 实例的基本 URL:GenderizeService
// some code builder.Services.AddScoped<IGenderizeService, GenderizeService>(); builder.Services.AddHttpClient<IGenderizeService, GenderizeService>( client => client.BaseAddress = new Uri("https://api.genderize.io/") ); var app = builder.Build(); // some more code
That's it! Can you spot the error?
The error was quite simple, but it took me a while to spot:
In the constructor I was injecting an :IHttpClientFactory
public GenderizeService(IHttpClientFactory httpClientFactory)
while in the host definition I was declaring an for a specific class:HttpClient
builder.Services.AddHttpClient<IGenderizeService, GenderizeService>
Apparently, even if we've specified how to create an instance for a specific class, we could not build it using an IHttpClientFactory.
So, here are 2 ways to solve it.
Named HttpClients are a helpful way to define a specific HttpClient and use it across different services.
It's as simple as assigning a name to an HttpClient instance and then using the same name when you need that specific client.
So, define it in the Startup method:
builder.Services.AddHttpClient("genderize", client => client.BaseAddress = new Uri("https://api.genderize.io/") );
and retrieve it using :CreateClient
public GenderizeService(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } public async Task<GenderProbability> GetGenderProbabiliy(string name) { var httpClient = _httpClientFactory.CreateClient("genderize"); var response = await httpClient.GetAsync($"?name={name}"); var result = await response.Content.ReadFromJsonAsync<GenderProbability>(); return result; }