ASP.NET Core DI构造函数与RequestServices

Mak*_*kla 4 c# dependency-injection .net-core asp.net-core

为什么要通过HttpContext.RequestServicesIServiceProvider考虑不良做法请求服务.我可以在这个地方读到这句话:

建议使用构造函数注入而不是使用RequestServices获取它.


我的想法恰恰相反.尽可能使用RequestServices.让我解释一下原因.我想保持控制器尽可能小,所以我创建了单独的服务.这样,我的控制器很干净:

public class MyController : Controller
{
    public MyController(IMyServices MyServices){}

    public async Task<IActionResult> GetSomething(int parameter)
    {
       return await this.MyServices.SomeMethod(parameter);
    }
}
Run Code Online (Sandbox Code Playgroud)

所有服务都从base继承,其中包含用于管理权限的逻辑,缓存sql请求....
使用构造函数方法,我得到了非常复杂的调用库系统:

public class MyBaseService
{
    public MyBaseService(ILogger Logger, AppDbContext Context, IMemoryCache Cache) { }

    public bool HasRight(string right) { return true; }

    public bool IsLoggedIn() { return true; }
}

public class MyServices : MyBaseService
{
    public MyServices(ILogger Logger, AppDbContext Context, IMemoryCache Cache) : base(Logger, Context, Cache)
    {    
    }
}
Run Code Online (Sandbox Code Playgroud)

但随着GetRequiredService我简化基于构造函数的调用:

public class MyBaseService2
{
    private ServiceProvider _ServiceProvider;
    public MyBaseService2(IServiceProvider ServiceProvider)
    {

    }

    protected ILogger Logger { get { return this._ServiceProvider.GetRequiredService<ILogger>(); } }

    protected AppDbContext Context { get { return this._ServiceProvider.GetRequiredService<AppDbContext>(); } }

    protected IMemoryCache Cache { get { return this._ServiceProvider.GetRequiredService<IMemoryCache>(); } }

    public bool HasRight(string right) { return true; }

    public bool IsLoggedIn() { return true; }
}

public class MyServices2 : MyBaseService2
{
    public MyServices2(IServiceProvider ServiceProvider) : base(ServiceProvider)
    {    
    }
}
Run Code Online (Sandbox Code Playgroud)

是的,BaseService包含更多代码,但是当我需要BaseService中的其他服务时,不需要修复每个类的基础构造函数调用.我的所有服务都有更简单的构造函数(只是IServiceProvider).

如果我反对构造函数方法.ServiceProvider.GetRequiredService如果生命周期是Scoped,如果调用MyServices,是否有任何性能损失.

Ste*_*ven 6

为什么通过HttpContext.RequestServices或IServiceProvider请求服务会考虑不好的做法.

这被认为是一种不好的做法,因为它是Service Locator反模式的一种实现.

您试图通过将许多常见的依赖项和公共逻辑移动到基类中来保持控制器类较小,但这本身就是一种反模式,因为:

  • 即使从基类解析了依赖关系,这些依赖关系仍然是隐藏的,正如本文所解释的那样.这意味着从单元测试和DI容器中隐藏了依赖关系,DI容器将无法对对象图进行分析.
  • 将依赖项移动到基类不会降低类的复杂性,因为基类总是与派生类强耦合.
  • 它导致许多职责被塞入基类,这将导致基类违反单一责任原则.这可以迫使基类成为神级并在不断变化之下.

基类使用继承,而软件开发中的普遍共识是你应该支持Composition而不是继承.

既然你应该喜欢组合,这会自动导致依赖注入.如果没有基类,就会更容易发现单一责任原则违规,因为您的构造函数将获得更多参数.再次注意,使用Service Locator时,依赖项的数量不会改变,它们更难计算.

你应该接受这样一个事实,即Constructor Injection容易导致Constructor过度注入,因为这表明我们的类做得太多,这是一个我们应该重新设计这样的类的信号.

而不是在基类中实现诸如日志记录,缓存和授权之类的横切关注点,而是使用组合来实现它们.例如,您可以使用中间件,装饰器拦截器将横切关注点应用于请求(或此类请求的特定服务).


归档时间:

查看次数:

1355 次

最近记录:

7 年,9 月 前