使用动态基地址改装客户端
Posted
技术标签:
【中文标题】使用动态基地址改装客户端【英文标题】:Refit Client using a dynamic base address 【发布时间】:2020-02-24 23:11:13 【问题描述】:我正在使用 Refit 在 asp.net core 2.2 中使用 Typed Client 调用 API,该 API 目前使用配置选项中的单个 BaseAddress 进行引导:
services.AddRefitClient<IMyApi>()
.ConfigureHttpClient(c => c.BaseAddress = new Uri(myApiOptions.BaseAddress);)
.ConfigurePrimaryHttpMessageHandler(() => NoSslValidationHandler)
.AddPolicyHandler(pollyOptions);
在我们的配置 json 中:
"MyApiOptions":
"BaseAddress": "https://server1.domain.com",
在我们的 IMyApi 界面中:
public IMyAPi interface
[Get("/api/v1/question/")]
Task<IEnumerable<QuestionResponse>> GetQuestionsAsync([AliasAs("document_type")]string projectId);
当前服务示例:
public class MyProject
private IMyApi _myApi;
public MyProject (IMyApi myApi)
_myApi = myApi;
public Response DoSomething(string projectId)
return _myApi.GetQuestionsAsync(projectId);
我现在需要在运行时根据数据使用不同的 BaseAddress。我的理解是 Refit 将 HttpClient 的单个实例添加到 DI 中,因此在运行时切换 BaseAddresses 不会直接在多线程应用程序中工作。现在注入 IMyApi 实例并调用接口方法 GetQuestionsAsync 非常简单。此时设置 BaseAddress 为时已晚。如果我有多个 BaseAddress,是否有一种简单的方法可以动态选择一个?
示例配置:
"MyApiOptions":
"BaseAddresses":
"BaseAddress1": "https://server1.domain.com",
"BaseAddress2": "https://server2.domain.com"
未来服务示例:
public class MyProject
private IMyApi _myApi;
public MyProject (IMyApi myApi)
_myApi = myApi;
public Response DoSomething(string projectId)
string baseUrl = SomeOtherService.GetBaseUrlByProjectId(projectId);
return _myApi.UseBaseUrl(baseUrl).GetQuestionsAsync(projectId);
更新 根据接受的答案,我最终得到以下结果:
public class RefitHttpClientFactory<T> : IRefitHttpClientFactory<T>
private readonly IHttpClientFactory _clientFactory;
public RefitHttpClientFactory(IHttpClientFactory clientFactory)
_clientFactory = clientFactory;
public T CreateClient(string baseAddressKey)
var client = _clientFactory.CreateClient(baseAddressKey);
return RestService.For<T>(client);
【问题讨论】:
【参考方案1】:注入 ClientFactory 而不是客户端:
public class ClientFactory
public IMyApi CreateClient(string url) => RestService.For<IMyApi>(url);
public class MyProject
private ClientFactory _factory;
public MyProject (ClientFactory factory)
_factory = factory;
public Response DoSomething(string projectId)
string baseUrl = SomeOtherService.GetBaseUrlByProjectId(projectId);
var client = _factory.CreateClient(baseUrl);
return client.GetQuestionsAsync(projectId);
【讨论】:
谢谢。 2个问题。 1)这对启动引导程序有何影响,即我是否只需删除 .ConfigureHttpClient() 调用? 2)也许我应该在问题中说这个,但是会有很多像 DoSomething() 这样的函数调用 IMyApi 上的各种端点。有没有办法从 MyProject 重构 Client Creation 并巧妙地将其注入,否则我将在每个方法中重复 DoSomething() 中的前两行? 我不确定引导,这取决于您使用的 DI 方法。一种可能性是完全放弃引导并在您的 DI 容器中注册ClientFactory
您可以将工厂的Create
方法更改为CreateForProject(string projectId)
并在该方法中查找URL。
我注意到的一件事是 RestService.For以上是关于使用动态基地址改装客户端的主要内容,如果未能解决你的问题,请参考以下文章