有时候我们在服务注册的时候会遇到这样一个场景,我们的同一个接口,有着多个实现,且我们还要同时使用这些实现的时候,这个时候该怎么办?我们可以使用键控服务依赖注入
键控服务依赖注入(Keyed Dependency Injection) 是 .NET 8 引入的新特性,允许你使用键(Key) 来区分同一接口的多个实现,它允许你注册接口的多个实现,每个实现都与一个唯一键相关联,然后基于该键解析所需的实现。
实现
键控服务依赖注入的方式很简单,下面我将从一个例子来说说如何实现
例:我们有一个存储数据的服务,我们既需要存在文件中也需要存在数据库中,这时候我们就会有两个服务的实现
基础类
public interface IDataService
{
void SaveData(string data);
}
public class LocalDataStorage : IDataService
{
public void SaveData(string data)
{
Console.WriteLine("方法1: " + data);
}
}
public class FileDataStorage : IDataService
{
public void SaveData(string data)
{
Console.WriteLine("方法2: " + data);
}
}
注册
我们通过名称为不同的实现传入了名称
builder.Services.AddKeyedSingleton<IDataService, LocalDataStorage >("Fun1");
builder.Services.AddKeyedSingleton<IDataService, FileDataStorage >("Fun2");
解析服务
1.构造函数获取
我们可以在构造函数中进行注入,在这里我们需要用到[FromKeyedServices(“名称”))
特性来标记需要获取哪个实现。
public class DataController : ControllerBase
{
private readonly IDataService dbService;
private readonly IDataService fileService;
public DataController(
[FromKeyedServices("Fun1")] IDataService dbService,
[FromKeyedServices("Fun2")] IDataService fileService)
{
dbService= dbService;
fileService= fileService;
}
}
在例子中我们在构造函数中注入了两种实现。
2.通过 IServiceProvider 手动解析
public class MyService
{
private readonly IDataService _dbService;
public MyService(IServiceProvider serviceProvider)
{
_dbService = serviceProvider.GetRequiredKeyedService<IDataService>("Fun1");
}
}
建议
我们在使用键控服务依赖注入时,我们尽量不使用字符串这种硬编码作为KEY名称,建议使用nameof或者枚举作为KEY值进行服务的解析
优势
NET 8键控服务依赖项注入功能弥补了之前版本接口不能多个实现的缺陷。键控服务依赖项注入提供了一种强大的机制来管理和解析接口的多个实现。它允许开发人员根据提供的密钥选择特定的实现,从而实现更灵活、更高效的应用程序设计。
往期推荐
大家如何需要了解依赖注入更详细的内容,可以阅读我之前的文章
.NET依赖注入IOC你了解吗?