当前位置: 首页 > 知识库问答 >
问题:

ASP。NET核心DI构造函数与RequestServices[重复]

窦啸
2023-03-14

为什么通过HttpContext.RequestServicesIServiceProvider请求服务被认为是不良做法。我可以到处阅读这条语句:

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

我的想法正好相反。尽可能使用Request estServices。让我解释一下为什么。我想让控制器尽可能小,这样我就可以创建单独的服务。这样,我的控制器就干净了:

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

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

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

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)
    {    
    }
}

但是使用Get必需服务我简化了基于构造函数的调用:

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)
    {    
    }
}

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

如果我反对构造函数方法。如果调用ServiceProvider,是否会影响性能。如果存在生存期范围,则对MyServices执行GetRequiredService

共有1个答案

公西俊能
2023-03-14

为什么通过HttpContext请求服务。RequestServices或IServiceProvider认为这是不良做法。

这被认为是一种不好的做法,因为它是服务定位器反模式的实现。

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

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

基类使用继承,而软件开发中的普遍共识是,您应该更喜欢组合而不是继承。

由于您应该支持组合,这会自动导致依赖注入。如果没有基类,立即发现违反单一职责原则的情况会变得更容易,因为构造函数将获得更多参数。再次注意,使用服务定位器时,依赖项的数量不会更改,只是更难计数。

您应该接受构造函数注入很容易导致构造函数过度注入的事实,因为这表明我们的类做得太多,并且这是我们应该重新设计此类类的信号。

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

 类似资料:
  • .NET核心和ASP.NET核心到底有什么区别?

  • 我的问题和这个差不多。 ASP。Net Core与EF Core和CosmosDB-身份问题 提供的答案不起作用。这会产生其他问题。当我从升级我的应用程序时,这些错误开始出现。NET Core 3.1 to。净5。降级应用程序使所有错误都消失了。显然,这个问题与efcore 5中引入的对cosmos的乐观并发支持有关。 https://docs.microsoft.com/en-us/ef/cor

  • 我有两台服务器使用相同的ASP。NET核心标识后端。我使用以下命令生成密码重置令牌: 我通过电子邮件链接发送此令牌。当用户单击链接时,他们会被带到一个单独的站点,该站点应提供一个用户界面来更改密码。以下代码处理用户提交令牌及其新密码的密码: 在第二台服务器上,标识结果总是返回false,因为“无效令牌”。 通过查看源代码,我看到令牌是使用IP地址生成的(因此我理解令牌验证失败的原因)。 我的问题是

  • 最近,在Ninject DI中配置实体框架DbContext生存期时,我一直在挖掘.NET核心依赖项注入,因为它已经具有注册DbContext的功能,可以在这里找到。默认上下文生存时间为。 在代码peek中,我们可以读到在ASP.NET应用程序中,“作用域”的意思是: 范围是围绕每个服务器请求创建的 .NET核心DI生命周期设置是如何工作的,它的生命周期是什么? 在Ninject DI中是否可能实

  • 所以我正在我的Java项目(Google Guice)中实现一个依赖注入框架,一切都很好,我喜欢它,但是有一个小问题;我想为我的主项目的类创建一个静态实例(实例化依赖项等)。但是我不知道使用Guice实例化它的任何方法,我不能手动实例化它,因为我在它的构造函数中使用DI(我在构造函数中有对象),这意味着我不能访问实例化该类所需的类的非静态变量。我试着使用一个提供者,但是我真的不明白在哪里绑定它,因

  • 我们正在开发具有移动部分和网络用户界面的应用程序。Web UI使用角,我们在后端配置cors时遇到了问题。我们的代码如下(只是对我们的问题很重要的代码): 从stackoverflow上的文档和其他帖子来看,这应该是可行的,但不是。我们错过了什么? thnx 编辑: 这是邮递员的请求: 卷曲'https://guw.azurewebsites.net/api/token'-X OPTIONS-H'