我正在为 .Net Core 编写控制台应用程序,并使用 Microsoft.Extensions.DependencyInjection 包。
控制台应用程序将在命令行进行切换,这将改变其行为,但每次的意图都保持不变:
- 从数据库中获取数据,
- 将所述数据整理成通用格式,
- 输出某种报告,
- 并将其发送到某个目的地。
我正在考虑做这样的事情:
string actionSwitch = "a"; // this would come from the command line
var serviceCollection = new ServiceCollection();
switch (actionSwitch)
{
case "a": // set up bindings for application mode a
serviceCollection.AddSingleton<IDatabaseReaderService, ReadFromMySqlService>();
serviceCollection.AddSingleton<IReportGeneratorService, HtmlReportGeneratorService>();
serviceCollection.AddSingleton<IReportOutputService, OutputReportToDiskService>();
break;
case "b": // set up bindings for application mode b
serviceCollection.AddSingleton<IDatabaseReaderService, ReadFromXmlFileService>();
serviceCollection.AddSingleton<IReportGeneratorService, PdfReportGeneratorService>();
serviceCollection.AddSingleton<IReportOutputService, OutputReportToFtpService>();
break;
}
serviceCollection.AddSingleton<IReportProcessService, ReportProcessService>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var process = serviceProvider.GetService<IReportProcessService>();
process.Execute();
即。绑定(bind)是根据用户在命令行的输入配置的。
最近才开始使用 DI,我看到的所有示例都遵循相同的模式:
- 在 Startup 或 Initialisation 类中声明绑定(bind)。
- 以后永远不要管他们。
上面的代码是否代表了 DI 的合理使用,或者在启动时使用应用程序逻辑来选择绑定(bind)是一种不好的做法?
最佳答案
您的问题标题有点误导。当我们在 DI 上下文中谈论“运行时”时,我们通常指的是配置绑定(bind)之后发生的所有事情。您正在做的不是运行时,而是启动时或配置时(不要与编译时混淆)时间顺便说一句)。
关于如何连接依赖项的决定是来自配置文件、命令行参数还是数据库,在这里无关紧要。只要它们都是在启动时已知的常量,您所做的就完全没问题,理智而且实际上是好的做法。
但是,当您实际上在运行时尝试更改绑定(bind)时,情况会发生变化,即在应用程序运行时更改容器。这将被认为是一种不好的做法。
有很多原因导致这种做法不好,并且有很多关于它的文章,例如 here和 here这就是 .NET 空间中的大多数 DI 容器现在转向不可变模型(1、2、3)的主要原因。
如果由于变量在运行时实际发生变化(与启动后不变的值相反)而需要调用不同的组件,建议使用适配器和代理类来隐藏调度发生在运行时的事实。例如,阅读 this .
TLDR;
- 在应用程序的生命周期内更改绑定(bind):差。
- 预先配置一次容器:好。
- 使用代理和适配器更改运行时使用的组件:好。
关于c# - 根据输入在启动时切换依赖注入(inject)绑定(bind) - 好的还是坏的做法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43825891/