首页 > 解决方案 > 如何简化asp.net核心依赖注入

问题描述

由于 asp.net core 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的构造函数更改时都更改所有控制器的构造函数并简化所有控制器的构造函数。

标签: asp.net-coredependency-injection

解决方案


您可以将 IServiceProvider 注入您的控制器并从中获取依赖项,但它不再是 DI,它被称为服务定位器模式。

public class HomeController
{
    private readonly ITestService _testService;

    public HomeController(IServiceProvider serviceProvider)
    {
        _testService = serviceProvider.GetRequiredService<ITestService>();
    }
}

建议不要使用服务定位器,因为:

1- 乍一看,您的控制器依赖关系并不明显。

2-为此编写单元测试更难。

3- 您的服务现在需要一个依赖项(IServiceProvider)。

仅在需要时使用服务定位器模式,例如将依赖项注入到 FilterAttributes 或 ValidationAttributes。(您也可以在这种情况下使用ServiceFilter。)


推荐阅读