c# - 通过使用反射的循环向 IServiceCollection 添加多个服务
问题描述
在 DI 容器设置期间,我有多个依赖手动设置的服务。例如,其中一些需要数据库连接字符串。所以不要写
services.AddTransient(typeof(TheInterface), typeof(TheImplementation));
我要做
services.AddTransient<TheInterface>(serviceProvider =>
{
// gather all the constructor parameters here
return new TheImplementation(/* pass in the constructor parameters */);
});
构造函数参数始终相同。我没有写多次,而是考虑创建这些服务的集合并循环访问该集合。我知道我可以通过使用类从类型创建新实例,Activator
但我正在努力从类型到泛型的转换。以下代码是用于演示目的的示例代码
public void SetupServices(IServiceCollection services, string databaseConnectionString)
{
IDictionary<Type, Type> servicesTypes = new Dictionary<Type, Type>()
{
{ typeof(MyInterface), typeof(MyImplementation) }
// ... more services here
};
foreach (KeyValuePair<Type, Type> servicesType in servicesTypes)
{
services.AddTransient <??? /* servicesType.Key does not work here */> (serviceProvider =>
{
return Activator.CreateInstance(servicesType.Value, databaseConnectionString /*, other params */);
});
}
}
我正在挣扎的位置是这条线
services.AddTransient <??? /* servicesType.Key does not work here */>
如何将服务接口类型转换为通用类型?我什至不确定这个循环是否值得付出努力......但目前我有 5 个可以使用它的服务。
解决方案
我不确定做一个通用版本是正确的方法。您的服务的“手动设置”可以使用选项模式修复吗?看起来您正在尝试通过数据库连接字符串。
它可能看起来像
// Options object
public class DatabaseOptions {
public string ConnectionString {get;set;}
}
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
[...]
// From configuration (appsettings.json)
services.Configure<DatabaseOptions>(Configuration.GetSection("Database"));
// OR directly
services.Configure<DatabaseOptions>(x => x.ConnectionString = "SomeString");
}
// The service
public class SomeService {
public SomeService(IOptions<DatabaseOptions> dbOptions) {
var connectionString = dbOptions.Value.ConnectionString;
}
}