使用 HttpClient 子类的类型化客户端



在我的应用程序中,我将拥有很少的TypedClient服务。 但是,这些类将共享一堆方法。 我的解决方案是创建CustomHttpClient:

public class CustomHttpClient:HttpClient
{
//here shared methods
}

然后,我的类型化客户端类将使用此派生类而不是标准 HttpClient:

public class MyService : IMyService
{
public SomeService(CustomHttpClient client, IConfiguration configuration){}
}

但是,如果我尝试在启动时注册此服务,则会收到一个错误,指出"MyService"没有合适的构造函数:

services.AddHttpClient<IMyService, MyService>();

在文档中,我发现:

类型化客户端是一个类,它接受 HttpClient 对象(通过其构造函数注入(并使用它来调用某个远程 HTTP 服务

这是否意味着它不能接受 HttpClient 的子类? 如果是这种情况,那么我唯一的解决方案是将共享方法实现为 HttpClient 扩展方法(我真的不喜欢这个解决方案(。 是否有解决方法,或者扩展方法是我唯一的出路? 我也尝试注册自定义HttpClient,以便DI容器找到它,但错误仍然相同。 你能给我什么建议?

这是否意味着它不能接受 HttpClient 的子类?

是的。

如果是这种情况,那么我唯一的解决方案是将共享方法实现为 HttpClient 扩展方法

不。 根据文档,类型客户端封装了一个 HttpClient,而不是扩展它。 在构造函数中配置 HttpClient,然后将自定义方法添加到使用封装的 HttpClient 实例的类型化客户端。

如果您不想将框架的模式用于 HttpClient 处理,您可以自由创建自己的模式,但这可能不值得付出努力。

可以具有共享基类的类型化客户端。 例如

public class MyBaseTypedClient
{
public HttpClient Client { get; }
public MyBaseTypedClient(HttpClient client)
{
client.BaseAddress = new Uri("https://api.github.com/");
// GitHub API versioning
client.DefaultRequestHeaders.Add("Accept",
"application/vnd.github.v3+json");
// GitHub requires a user-agent
client.DefaultRequestHeaders.Add("User-Agent",
"HttpClientFactory-Sample");
Client = client;
}
//other methods
}
public class MyTypedClient : MyBaseTypedClient
{
public MyTypedClient(HttpClient client) : base(client) { }
}

如果你只需要添加常用方法,你可以创建一个接口,这些方法的默认实现,那么你只需要继承你的IMyService与该接口。

您还可以查看下面的链接,其中包含一些有趣的解决方法。

https://github.com/dotnet/extensions/issues/1988

我认为这就是你想要做的:

(1( 创建您的基本 MyBaseTyped客户端,如下所示:


public interface IMyBaseTypedClient
{ 
//other methods
//like FetchAsync(), PostAsync()
}
public class MyBaseTypedClient
{
private HttpClient _client
public MyBaseTypedClient(HttpClient client)
{
_client = client;
}
//other methods
//like FetchAsync(), PostAsync()
}

(2( 然后创建类型化客户端,如下所示:

public interface IServiceOne: IMyBaseTypedClient{ }
public class ServiceOne: MyBaseTypedClient, IServiceOne
{
public ServiceOne(HttpClient httpClient) : base(httpClient)
{
}
}
public interface IServiceTwo: IMyBaseTypedClient{ }
public class ServiceTwo: MyBaseTypedClient, IServiceTwo
{
public ServiceTwo(HttpClient httpClient) : base(httpClient)
{
}
}

(3(然后按以下方式注册

services
.AddHttpClient<IServiceOne, ServiceOne>(c => c.BaseAddress = new Uri("https://serviceone.com"));
.AddHttpClient<IServiceTwo, ServiceTwo>(c => c.BaseAddress = new Uri("https://servicetwo.com");

(4(然后按如下方式注射

public void SomeMethodThatNeedsOne(IServiceOne serviceOne)
{
//etc
}
public void SomeMethodThatNeedsTwo(IServiceTwo serviceTwo)
{
//etc
}

最新更新