C# 使用相同接口但不同构造函数参数值注册多个单例
我陷入困境,需要一些建议或解决办法 具有ASP.NET核心3.1的web API Startup.csC# 使用相同接口但不同构造函数参数值注册多个单例,c#,dependency-injection,.net-core-3.1,azure-servicebus-topics,C#,Dependency Injection,.net Core 3.1,Azure Servicebus Topics,我陷入困境,需要一些建议或解决办法 具有ASP.NET核心3.1的web API Startup.cs services.AddSingleton<ITopicClient>(s => new TopicClient({connectionstring},{topic})); 我需要向不同的主题发送消息。我想在startup.cs中注册具有不同主题名称的服务。我想重新使用topicClient连接 AddSingleton(s=>newtopicClient({connect
services.AddSingleton<ITopicClient>(s => new TopicClient({connectionstring},{topic}));
我需要向不同的主题发送消息。我想在startup.cs中注册具有不同主题名称的服务。我想重新使用topicClient连接
AddSingleton(s=>newtopicClient({connectionstring},{topic1})
AddSingleton(s=>newtopicClient({connectionstring},{topic2})
如何通过使用相同接口注册相同类型的单例实例来实现这一点
提前谢谢你 您已经可以将多个实例注册为同一接口,因此当您注册时:
services.AddSingleton<ITopicClient>(_ => new TopicClient("topic1"));
services.AddSingleton<ITopicClient>(_ => new TopicClient("topic2"));
如果需要所有实例,则应解析/注入IEnumerable
class主题存储库
{
公共主题存储库(IEnumerable客户端)
{
//客户端包含topic1和topic2
}
}
您可以使用一个客户端解析程序,该解析程序使用一个围绕客户端的包装器来保存已注册的客户端。
首先在您的客户机周围创建一个包装器,使用名称或枚举说明如何解析它。由于我不喜欢神奇的字符串,我决定在示例中使用枚举
// Wrapper for your TopicClients
public interface ICustomTopicClient
{
public ITopicClient TopicClient { get; }
public TopicName TopicName { get; }
}
// Implement the ICustomTopicClient interface
public class CustomTopicClient : ICustomTopicClient
{
public ITopicClient TopicClient { get; }
public TopicName TopicName { get; }
public CustomTopicClient(ITopicClient topicClient, TopicName topicName)
{
TopicClient = topicClient;
TopicName = topicName;
}
}
// Enum for how to resolve the requested TopicClient
public enum TopicName
{
Topic1 = 0,
Topic2 = 1
}
// Register all ICustomTopicClients in your container
services.AddSingleton<ICustomTopicClient>(s => new CustomTopicClient(new TopicClient({connectionstring},{topic}), TopicName.Topic1));
services.AddSingleton<ICustomTopicClient>(s => new CustomTopicClient(new TopicClient({connectionstring},{topic2}), TopicName.Topic2));
您可以使用相同的模式并使用IQueueClients扩展解析器。并添加一个resolve方法,通过QueueName枚举返回IQueueClient。您不需要为每个主题提供服务,你需要的是一个连接工厂,负责管理你的单个连接,然后你将其注入到你的服务中并调用它来为你返回连接。或者为每个主题创建一个类型,并为每个主题注册一个Topic123TopicClient。像数据库连接字符串一样,你的应用程序可能会使用一小部分固定的主题。有没有其他方法可以实现,因为目前我只需要5个主题的TopicClient实例,但它可能会增长。?
services.AddSingleton<ITopicClient>(_ => new TopicClient("topic1"));
services.AddSingleton<ITopicClient>(_ => new TopicClient("topic2"));
// instance = topic2
var instance = container.GetService<ITopicClient>();
class TopicRepository
{
public TopicRepository(IEnumerable<ITopicClient> clients)
{
// clients contains topic1 and topic2
}
}
// Wrapper for your TopicClients
public interface ICustomTopicClient
{
public ITopicClient TopicClient { get; }
public TopicName TopicName { get; }
}
// Implement the ICustomTopicClient interface
public class CustomTopicClient : ICustomTopicClient
{
public ITopicClient TopicClient { get; }
public TopicName TopicName { get; }
public CustomTopicClient(ITopicClient topicClient, TopicName topicName)
{
TopicClient = topicClient;
TopicName = topicName;
}
}
// Enum for how to resolve the requested TopicClient
public enum TopicName
{
Topic1 = 0,
Topic2 = 1
}
// Register all ICustomTopicClients in your container
services.AddSingleton<ICustomTopicClient>(s => new CustomTopicClient(new TopicClient({connectionstring},{topic}), TopicName.Topic1));
services.AddSingleton<ICustomTopicClient>(s => new CustomTopicClient(new TopicClient({connectionstring},{topic2}), TopicName.Topic2));
public interface IMessageClientResolver
{
ITopicClient ResolveClient(TopicName name);
}
public class MessageClientResolver : IMessageClientResolver
{
private readonly Dictionary<TopicName, ITopicClient> topicClients;
public MessageClientResolver(IEnumerable<ICustomTopicClient> clients)
{
topicClients = clients.ToDictionary(k => k.TopicName, v => v.TopicClient);
}
public ITopicClient ResolveClient(TopicName name)
{
topicClients.TryGetValue(name, out var client);
if (client is null)
throw new ArgumentException(nameof(client));
return client;
}
}
services.AddSingleton<IMessageClientResolver, MessageClientResolver>();
public class Foo
{
private readonly ITopicClient topicClient;
private readonly ITopicClient topicClient2;
public Foo(IMessageClientResolver clientResolver)
{
topicClient = clientResolver.ResolveClient(TopicName.Topic1);
topicClient2 = clientResolver.ResolveClient(TopicName.Topic2);
}
}