【发布时间】:2020-09-01 18:54:45
【问题描述】:
我在尝试使用依赖注入时遇到了一些麻烦,需要帮助。
我有一个服务IService 在我的应用程序中以几种不同的方式实现。
ServiceA : IService { public ServiceA(IDependencyA A, IDependency B) {...} }
ServiceB : IService { public ServiceB(IDependencyA A, IDependency B) {...} }
ServiceC : IService { public ServiceC(IService serviceA, IService serviceB) {...} }
在我的startup.cs 文件中,我将根据我的配置文件中的参数选择使用哪一个。像这样的:
var service = Configuration["AppConfig:Service:ID"];
switch(service) {
case "A":
services.AddTransient<IService, ServiceA>();
case "B":
services.AddTransient<IService, ServiceB>();
case "C":
// ??
}
我能够非常轻松地创建和使用服务 A 和服务 B。我事先注入了它们的依赖项 A 和 B 并且它们被创建得很好。问题在于第三项服务。我需要将另外两个服务注入其中。我的问题是:最好的方法是什么?
有没有一种方法可以创建服务 A 和 B 的具体实现,但以某种方式在其构造函数中使用注入的依赖项 A 和 B?我是否必须弄乱接口才能使其正常工作?也许我必须更改 ServiceC 的构造函数以接受 A 和 B 的具体实现?
更新:不知道这是否是最好的解决方案,但我最终做了以下事情来让它工作。
...
case "C":
services.AddTransient<ServiceA>();
services.AddTransient<ServiceB>();
services.AddTransient<IService>(s =>
new ServiceC(
s.GetService<ServiceA>(),
s.GetService<ServiceB>()
));
【问题讨论】:
-
添加更多关于服务C的细节。如果它确实需要这2个具体实现,那么你应该改变构造函数。否则会破坏 Liskov 替换原则。修复开关,没有中断,服务A注册了2次。
-
服务 C 的目标是使用服务 A 的实现,但是如果服务 A 不能提供正确的结果,则回退到服务 B 的结果。
-
为所需服务创建工厂模式,并在需要时实例化它们。并非所有事情都需要由 DI() 处理
-
根据您在此处的最后一条评论,基于结果的服务使用情况,您可以使用类似于Strategy Pattern 的概念以更简洁的方式实现此目的。如果您能预测结果是否会成功,那当然会更好。
-
@mymemesarespiciest 即使您不直接使用 Polly,您也应该了解它是如何工作的,它如何解决您可能遇到的相同问题
标签: c# asp.net-core dependency-injection