c# - ASP.NET Core 创建类实例,其中类可能使用 DI - 寻找模式建议
问题描述
我有一个问题,我需要用一些配置数据实例化一个类,但该类可能使用它从 DI 容器收集的其他类。我注册了许多服务Startup
,我可以毫无问题地从控制器和服务访问它们 - 运行良好。
问题是我有一个接口,IProvider
它有许多实现它的类ProviderA
,ProviderB
等等。在运行时,根据用户的选择,我需要创建这些类之一的实例并在其上调用一些方法。
该类需要一些配置数据(它们用于与外部系统通信),我需要弄清楚如何传递配置数据以及允许 DI 为那些需要其他服务的类工作。
IProvider
接口定义为:
public interface IProvider
{
Task<string> ValidateAsync();
}
使用它的类可能是这样的:
public class ProviderA: IProvider
{
private readonly SMSService _smsService;
public ProviderA(SMSService smsService, string configuration)
{
_smsService = smsService;
//do something with configuration
}
public Task<string> ValidateAsync()
{
//validate connection using passed in configuration
throw new NotImplementedException();
}
}
根据用户输入,我需要创建该类的一个新实例,但希望该类解决其自己的依赖关系(SMSService
在本例中)。我还注意到SMSService
可能还有其他依赖项(dbContext
等)。
我创建新实例的代码是计算对象的类型并创建一个实例:
provider = new ProviderA(configuration);
关于如何创建该对象的实例、传入参数并允许它获取自己的依赖项的任何想法?我怀疑我的方法不正确,但在过去,它运行良好,但现在使用 DI 给我带来了麻烦,因为需要获取各种服务并且需要传递参数。
解决方案
我建议在IProvider
界面中添加一些描述字段,例如:
public interface IProvider
{
Task<string> ValidateAsync();
ProviderType Type { get; }
}
它允许您注入接口的所有实现并根据用户输入选择其中一个:
public class MyService
{
private IEnumerable<IProvider> providers;
public MyService(IEnumerable<IProvider> providers)
{
this.providers = providers;
}
public Task Action(UserInput input)
{
var provider = providers.FirstOrDefault(el => el.Type == SmsProvider);
}
}
至于配置,你可以为每种类型的 Provider 创建 Config 类并注册它:
public class Config
{
public string SomeConfig { get; set; }
}
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(new Config());
}
public ProviderA(SMSService smsService, Config configuration)
{
}
甚至将配置放入 appsettings.json 并使用IOptions 模式
public void ConfigureServices(IServiceCollection services)
{
var section = Configuration.GetSection("ProviderA");
services.Configure<Config>(section);
}
并消费它:
public ProviderA(SMSService smsService, IOptions<Config> configuration)
{
var config = configuration.Value;
}
推荐阅读
- powershell - 从进程的命令行中提取参数
- c - 在 C 中使用 getchar() 读取输入时是否需要分配内存?
- laravel - Laravel、Nginx 和 Docker 容器,权限被拒绝
- laravel - 如何在 laravel 中显示评论和回复评论
- python - numpy 按类型元素搜索并更改它
- jquery - Asp.net 使用 ajax (javascript) 从布局页面中的 api 控制器获取数据
- excel - Excel VBA 相关组合框
- jquery - 如何在 DataTables 中使用 JS/Jquery-Functions
- node.js - 是否在 package.json 中使用确切的版本号?
- android - 如何使用 ConstraintLayout 将滚动视图设置为屏幕的一半