由于asp.net核心DI仅提供构造函数注入和方法注入。 如果有很多服务需要注入。 与其在构造函数内部写很多东西,而不必经常更改构造函数。 我可以只使用某种提供程序,以便在控制器内的任何地方获得服务吗?
代替:
public class HomeController : BaseController
{
public HomeController(
IEmailService emailService,
ISMSService smsService,
ILogService logService,
IProductRepository _productRepository)
:base(emailService,smsService,logService)
{
}
public IActionResult()
{
_emailService.SendSomething();
}
...
}
public class BaseController : Controller
{
protected readonly IEmailService _emailService;
protected readonly ISMSService _smsService;
protected readonly ILogService _logService;
public BaseController(
IEmailService emailService,
ISMSService smsService,
ILogService logService)
{
_emailService = emailService;
_smsService = smsService;
_logService = logService;
}
}
使用某种提供程序,例如:
public class HomeController : BaseController
{
public HomeController(IDIServiceProvider provider)
:base(provider)
{
}
public IActionResult()
{
_provider.GetScopedService<IEmailService>().SendSomething();
}
...
}
public class BaseController : Controller
{
protected readonly IDIServiceProvider _provider;
public BaseController(IDIServiceProvider provider)
{
_provider = provider;
}
}
因此,当BaseController的构造函数发生更改并简化所有控制器的构造函数时,不必每次都更改所有控制器的构造函数。
答案 0 :(得分:6)
您可以将IServiceProvider注入到控制器中并从中获取依赖关系,但是它不再是DI了,它称为 Service Locator 模式。
public class HomeController
{
private readonly ITestService _testService;
public HomeController(IServiceProvider serviceProvider)
{
_testService = serviceProvider.GetRequiredService<ITestService>();
}
}
不使用服务定位器是recommended,因为:
1-乍一看,您对控制器的依赖性并不明显。
2-为此很难编写单元测试。
3-现在您的服务还需要一个依赖项(IServiceProvider)。
仅在需要将依赖项注入FilterAttributes或ValidationAttributes时,才使用Service Locator模式。 (您也可以在这种情况下使用ServiceFilter。)