英文:
How to dynamically choose what concrete class to use in dependency injection
问题
I usually write something like this for my DI
:
var serviceProvider = new ServiceCollection()
.AddSingleton<ISomething, Something>()
.AddSingleton<IOutputMaker, XMLOutputMaker>()
.AddSingleton<IConfiguration>(Program.configuration)
.BuildServiceProvider();
But now let's say I read from a config file
what type
of output I should generate. Notice that above I have this line:
.AddSingleton<IOutputMaker, XMLOutputMaker>()
But I want to be more flexible and say for example if config file says XML
then that, if config file says XLSX
then maybe this:
.AddSingleton<IOutputMaker, ExcelOutputMaker>()
How can I do that to be more flexible?
I don't know how. Maybe I can call that BuildServiceProvider
multiple times?
英文:
I usually write something like this for my DI
:
var serviceProvider = new ServiceCollection()
.AddSingleton<ISomething, Something>()
.AddSingleton<IOutputMaker, XMLOutputMaker>()
.AddSingleton<IConfiguration>(Program.configuration)
.BuildServiceProvider();
But now let's say I read from a config file
what type
of output I should generate. Notice that above I have this line:
.AddSingleton<IOutputMaker, XMLOutputMaker>()
But I want to be more flexible and say for example if config file says XML
then that, if config file says XLSX
then maybe this:
.AddSingleton<IOutputMaker, ExcelOutputMaker>()
How can I do that to be more flexible?
I don't know how. Maybe I can call that BuildServiceProvider
multiple times?
答案1
得分: 2
以下是您要的翻译内容:
您可以注册具体的实现,然后注册一个工厂,从配置中查询某些内容(我使用了 options,但您也可以直接解析 IConfiguration
)以确定要返回哪个。
services.AddOptions<SomeOptions>().BindConfiguration("something");
services.AddSingleton<SomethingImplementationOne>();
services.AddSingleton<SomethingImplementationTwo>();
services
.AddSingleton<ISomething>(sp => {
var opts = sp.GetRequiredService<IOptions<SomeOptions>>();
switch (opts.DefaultService)
{
case "One":
return sp.GetRequiredService<SomethingImplementationOne>();
default:
return sp.GetRequiredService<SomethingImplementationTwo>();
}
});
为了完整起见,我的 SomeOptions
类如下所示:
public class SomeOptions
{
public string DefaultService { get; set; }
}
我的配置的 JSON 如下所示:
{
"something": {
"defaultService": "One"
}
}
英文:
You can register the concrete implementations, and then register a factory that consults something from the configuration (I've used options, but you could also just resolve IConfiguration
) to determine which one to return.
services.AddOptions<SomeOptions>().BindConfiguration("something");
services.AddSingleton<SomethingImplementationOne>();
services.AddSingleton<SomethingImplementationTwo>();
services
.AddSingleton<ISomething>(sp => {
var opts = sp.GetRequiredService<IOptions<SomeOptions>>();
switch (opts.DefaultService)
{
case "One":
return sp.GetRequiredService<SomethingImplementationOne>();
default:
return sp.GetRequiredService<SomethingImplementationTwo>();
}
});
For completeness, my SomeOptions
class looks like this:
public class SomeOptions
{
public string DefaultService { get; set; }
}
And my JSON for my configuration looks like this:
{
"something": {
"defaultService": "One"
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论