首页 > 解决方案 > 通过使用反射的循环向 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 个可以使用它的服务。

标签: c#asp.net-core.net-corereflectionasp.net-core-webapi

解决方案


我不确定做一个通用版本是正确的方法。您的服务的“手动设置”可以使用选项模式修复吗?看起来您正在尝试通过数据库连接字符串。

它可能看起来像

// 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;
    }
}

推荐阅读