我想在ASP.NET Core中实现依赖注入(DI)。因此,在将此代码添加到ConfigureServices方法后,这两种方法都可以工作。

ASP.NET Core中的services.AddTransient和service.AddScoped方法之间有什么区别?

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddScoped<IEmailSender, AuthMessageSender>();
}

当前回答

这张图片很好地说明了这个概念。不幸的是,我找不到这个图像的来源,但有人制作了它,他以图像的形式很好地展示了这个概念。

更新:图片参考:ASP.NET核心服务生命周期(Infographic),作者:@WaqasAnwar

其他回答

添加单体()

AddSingleton()在首次请求时创建服务的单个实例,并在需要该服务的所有地方重用该实例。

添加作用域()

在作用域服务中,对于每个HTTP请求,我们都会得到一个新实例。然而,在同一HTTP请求中,如果在多个位置(如视图和控制器中)需要服务,则为该HTTP请求的整个范围提供相同的实例。但是,每个新的HTTP请求都将获得服务的新实例。

添加过渡()

对于瞬时服务,无论服务实例是在同一HTTP请求的范围内还是跨不同HTTP请求,每次请求服务实例时都会提供一个新实例。

通过DbContext使用EntityFramework/Core可能是生命周期的最佳说明。

建议将DbContext和与DbContext交互的存储库连接到Scoped生存期,因为DbContext显然是一个有状态的构造。所以你不想使用Singleton,因为你最终会遇到各种并发问题。您不想使用Transient,因为DbContext不是线程安全的。记住,Transient适用于处理无状态对象/类的用例。

而且,由于大多数存储库都是由控制器调用的,所以使用作用域生存期确实很有意义。可以想象,作为事务的一部分,DbContext可以在单个操作方法期间多次调用。

本文没有直接讨论这些生存期,但对为什么Scoped生存期最适合DbContext给出了很好的解释。

https://mehdi.me/ambient-dbcontext-in-ef6/?msclkid=00251b05d01411ec8d85d232374f26d5

这张图片很好地说明了这个概念。不幸的是,我找不到这个图像的来源,但有人制作了它,他以图像的形式很好地展示了这个概念。

更新:图片参考:ASP.NET核心服务生命周期(Infographic),作者:@WaqasAnwar

使用哪一个

转瞬即逝的

因为它们每次创建时都会使用更多的内存和资源,并且会对性能产生负面影响对于状态很少或没有状态的轻量级服务,请使用此选项。

范围内的

当您想要维护请求中的状态时,更好的选项。

辛格尔顿

这些服务中的内存泄漏会随着时间的推移而增加。也可以节省内存,因为它们一旦在任何地方重复使用就会被创建。

在需要维护应用程序范围状态的地方使用Singleton。应用程序配置或参数、日志服务、数据缓存是可以使用单例的一些示例。

将具有不同生存期的服务注入另一个

切勿将作用域和瞬态服务注入Singleton服务。(这有效地将瞬时或作用域服务转换为单例。)从不将瞬态服务注入作用域服务(这会将瞬态服务转换为作用域。)

Singleton是应用程序生命周期中的单个实例领域作用域是作用域期间的单个实例请求,这意味着ASP.NET中的每个HTTP请求。瞬态是每个代码请求的单个实例。

通常,代码请求应该通过构造函数参数进行,如

public MyConsumingClass(IDependency dependency)

我想在@akazemis的回答中指出,DI上下文中的“服务”并不意味着RESTful服务;服务是提供功能的依赖项的实现。