用不同的配置多次注册同一个对象
本文关键字:注册 一个对象 配置 | 更新日期: 2023-09-27 18:02:32
我有这个api客户端ICommunicationClient(url, tenant)
注册在我的IoC容器。现在我面临的情况是,我可以有1到n api客户端。我需要登记所有的人,我不知道该怎么处理。我在SI中看到过这个RegisterCollection
我正在考虑使用ICommunicationClientProvider
作为实际客户端的包装器。它包含一个列表,其中包含所有已注册的客户端和用于检索它们的方法。我觉得这不是最好的方法,当然,它"迫使"我去触摸应用的其他部分。
public class CommunicationClientProvider : ICommunicationClientProvider
{
public CommunicationClientCollection CommunicationClientsCollection { get; set; }
public string Tenant { get; set; }
public ICommunicationClient GetClients()
{
return CommunicationClientsCollection[Tenant];
}
public void SetClients(CommunicationClientCollection clients)
{
CommunicationClientsCollection = clients;
}
}
public interface ICommunicationClientProvider
{
ICommunicationClient GetClients();
void SetClients(CommunicationClientCollection clients);
}
承载集合
public class CommunicationClientCollection : Dictionary<string, ICommunicationClient>
{
}
这里我将集合注册到SI
var clients = new CommunicationClientProvider();
foreach (var supportedTenant in supportedTenants)
{
clients.CommunicationClientsCollection
.Add(supportedTenant, new CommunicationClient(
new Uri(configuration.AppSettings["communication_api." + supportedTenant]),
new TenantClientConfiguration(supportedTenant)));
}
container.RegisterSingleton<ICommunicationClientProvider>(clients);
你知道更好的方法吗?这是一个正常的场景,例如当您有多个数据库时。
更新: - - ITenantContext部分这基本上就是我的租户上下文界面的样子:
public interface ITenantContext
{
string Tenant { get; set; }
}
这是我调用通信api的地方:
public class MoveRequestedHandler : IHandlerAsync<MoveRequested>
{
private readonly IJctConfigurationService _communicationClient;
private readonly ITenantContext _tenantContext;
public MoveRequestedHandler(IJctConfigurationService communicationClient, ITenantContext tenantContext)
{
_communicationClient = communicationClient;
_tenantContext = tenantContext;
}
public async Task<bool> Handle(MoveRequested message)
{
_tenantContext.Tenant = message.Tenant;
_communicationClient.ChangeApn(message.Imei, true);
return await Task.FromResult(true);
}
}
我在这里注册了ITenantContext
container.RegisterSingleton<ITenantContext, TenantContext>();
租户在MoveRequested
对象(message.Tenant
)中定义。如何使CommunicationClient意识到该租户?
如果添加ICommunicationClientProvider
抽象导致您在整个应用程序中进行彻底的更改,那么显然有什么地方出了问题。您通常应该能够添加功能并进行更改,而无需进行全面更改。事实上,我认为你们目前的设计已经允许这样做了。
你的ICommunicationClientProvider
)就像一个工厂,而工厂几乎从来都不是正确的解决方案。相反,使用Composite设计模式会好得多。例如:
sealed class TenantCommunicationClientComposite : ICommunicationClient
{
private readonly ITenantContext tenantContext;
private readonly Dictionary<string, ICommunicationClient> clients;
public TenantCommunicationClientComposite(ITenantContext tenantContext,
Dictionary<string, ICommunicationClient> clients) {
this.tenantContext = tenantContext;
this.clients = clients;
}
object ICommunicationClient.ClientMethod(object parameter) =>
this.clients[this.tenantContext.CurrentTenantName].ClientMethod(parameter);
}
你可以按以下方式注册这个类:
var dictionary = new Dictionary<string, ICommunicationClient>();
foreach (var supportedTenant in supportedTenants) {
dictionary.Add(supportedTenant, new CommunicationClient(
new Uri(configuration.AppSettings["communication_api." + supportedTenant]),
new TenantClientConfiguration(supportedTenant)));
}
container.RegisterSingleton<ICommunicationClient>(
new TenantCommunicationClientComposite(
new AspNetTenantContext(),
dictionary));
这里的ITenantContext
是一个抽象,它允许您获得代表当前请求运行的当前租户。AspNetTenantContext
是一种实现,它允许您在ASP中检索当前租户。网络应用程序。您可能已经编写了一些代码来检测当前租户;您可能需要将该代码移动到这样的AspNetTenantContext
类。