如何通过配置在asp.net core中动态决定AddSingleton的实现类?
摘要:有一些接口,我们也不知道最终谁来实现, 又或者不同的环境有不同的实现。于是我们希望通过配置来处理。 通过配置决定实际注入类 builder.Services.AddSingletonIfCfg<ISmsVerify
有一些接口,我们也不知道最终谁来实现, 又或者不同的环境有不同的实现。于是我们希望通过配置来处理。
//通过配置决定实际注入类
builder.Services.AddSingletonIfCfg<ISmsVerifyCodeService>(builder.Configuration, "SmsVerifyCodeService:TypeName");
那我们只需在appsetting.json中修改,以使用不同实现。下面注入的是:SmsAdapter.AliyunSMSVerifyCodeService, SmsAdapter
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"SmsVerifyCodeService": {
"TypeName": "SmsAdapter.AliyunSMSVerifyCodeService, SmsAdapter",
"Aliyun": {"AccessId": "yyyyyy",
"AccessSecret": "bbbb",
"SignName": "myapp",
"TemplateCode": "SMS_222"
}
}
}
具体的AddSingletonIfCfg方法在以下静态工具类提供
public static class DynamicServiceFactory
{
public static void AddSingletonIfCfg<T>(this IServiceCollection services, IConfiguration config, string configKey)
{
var typeName = config.GetValue<string>(configKey);
if (string.IsNullOrEmpty(typeName))
{
Console.WriteLine($" AddSingletonIfCfg miss configKey: {configKey} .");
return;
}
var type = Type.GetType(typeName);
if (type == null)
throw new Exception($" AddSingletonIfCfg miss typeName: {typeName} .");
if (!typeof(T).IsAssignableFrom(type))
throw new Exception($" AddSingletonIfCfg typeName: {typeName} not implement {typeof(T).FullName} .");
// 使用ActivatorUtilities创建实例并注册服务
services.AddSingleton(typeof(T), serviceProvider =>
{
try
{
return ActivatorUtilities.CreateInstance(serviceProvider, type);
}
catch (Exception ex)
{
throw new Exception($"Failed to create instance of type {typeName}.", ex);
}
});
}
}
好了,我们就可以增加一个类库项目SmsAdapter,一个类AliyunSMSVerifyCodeService来实现ISmsVerifyCodeService。
AliyunSMSVerifyCodeService类可以象在主程序中一样书写,可以使用注入的所有服务。
