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

我想在Asp.Net Core中实现dependency injection 。 因此,在将此代码添加到ConfigureServices方法之后,两种方式都有效。

services.AddTransientservice.AddScope方法之间有什么区别是Asp.Net Core?

public void ConfigureServices(IServiceCollection services) { // Add framework services. // Add application services. services.AddTransient(); services.AddScoped(); } 

TL; DR

瞬态物体总是不同的; 为每个控制器和每个服务提供一个新实例。

范围内的对象在请求中是相同的,但在不同的请求中是不同的。

Singleton对象对于每个对象和每个请求都是相同的。

有关更多说明, asp.net docs中的这个示例显示了不同之处:

要演示这些生存期和注册选项之间的区别,请考虑一个简单的接口,它将一个或多个任务表示为具有唯一标识符OperationId 。 根据我们如何配置此服务的生命周期,容器将为请求类提供相同或不同的服务实例。 为了明确请求哪个生命周期,我们将为每个生命周期创建一个类型选项:

 using System; namespace DependencyInjectionSample.Interfaces { public interface IOperation { Guid OperationId { get; } } public interface IOperationTransient : IOperation { } public interface IOperationScoped : IOperation { } public interface IOperationSingleton : IOperation { } public interface IOperationSingletonInstance : IOperation { } } 

我们使用单个类Operation实现这些接口,它在构造函数中接受Guid ,或者如果没有提供,则使用新的Guid

接下来,在ConfigureServices ,每个类型根据其命名生存期添加到容器中:

 services.AddTransient(); services.AddScoped(); services.AddSingleton(); services.AddSingleton(new Operation(Guid.Empty)); services.AddTransient(); 

请注意, IOperationSingletonInstance服务正在使用具有已知ID Guid.Empty的特定实例,因此在使用此类型时将清楚。 我们还注册了一个依赖于其他每种Operation类型的Operation ,以便在请求中明确该服务是为每个操作类型获取与控制器相同的实例,还是获取新实例。 所有这些服务都将其依赖项公开为属性,因此它们可以显示在视图中。

 using DependencyInjectionSample.Interfaces; namespace DependencyInjectionSample.Services { public class OperationService { public IOperationTransient TransientOperation { get; } public IOperationScoped ScopedOperation { get; } public IOperationSingleton SingletonOperation { get; } public IOperationSingletonInstance SingletonInstanceOperation { get; } public OperationService(IOperationTransient transientOperation, IOperationScoped scopedOperation, IOperationSingleton singletonOperation, IOperationSingletonInstance instanceOperation) { TransientOperation = transientOperation; ScopedOperation = scopedOperation; SingletonOperation = singletonOperation; SingletonInstanceOperation = instanceOperation; } } } 

为了演示对应用程序的单独单个请求内部和之间的对象生存期,该示例包括一个OperationsController ,它请求每种类型的IOperation类型以及一个OperationService 。 然后, Index操作将显示所有控制器和服务的OperationId值。

 using DependencyInjectionSample.Interfaces; using DependencyInjectionSample.Services; using Microsoft.AspNetCore.Mvc; namespace DependencyInjectionSample.Controllers { public class OperationsController : Controller { private readonly OperationService _operationService; private readonly IOperationTransient _transientOperation; private readonly IOperationScoped _scopedOperation; private readonly IOperationSingleton _singletonOperation; private readonly IOperationSingletonInstance _singletonInstanceOperation; public OperationsController(OperationService operationService, IOperationTransient transientOperation, IOperationScoped scopedOperation, IOperationSingleton singletonOperation, IOperationSingletonInstance singletonInstanceOperation) { _operationService = operationService; _transientOperation = transientOperation; _scopedOperation = scopedOperation; _singletonOperation = singletonOperation; _singletonInstanceOperation = singletonInstanceOperation; } public IActionResult Index() { // viewbag contains controller-requested services ViewBag.Transient = _transientOperation; ViewBag.Scoped = _scopedOperation; ViewBag.Singleton = _singletonOperation; ViewBag.SingletonInstance = _singletonInstanceOperation; // operation service has its own requested services ViewBag.Service = _operationService; return View(); } } } 

现在,对此控制器操作发出两个单独的请求: 第一次请求

第二个请求

观察哪个OperationId值在请求内和请求之间变化。

  • 瞬态物体总是不同的; 为每个控制器和每个服务提供一个新实例。

  • 范围内的对象在请求中是相同的,但在不同的请求中是不同的

  • Singleton对象对于每个对象和每个请求都是相同的(无论ConfigureServices中是否提供了实例)

在dotnet的dependency injection中,有三个主要的生命周期:

Singleton在整个应用程序中创建单个实例。 它首次创建实例,并在所有调用中重用相同的对象。

在范围内的每个请求中创建一次范围生存期服务。 它相当于当前范围内的Singleton。 例如。 在MVC中,它为每个http请求创建1个实例,但在同一Web请求中的其他调用中使用相同的实例。

每次请求时都会创建瞬态生命周期服务。 这种生命周期最适合轻量级,无状态服务。

在这里你可以找到和看到差异的例子:

http://dotnetliberty.com/index.php/2015/10/15/asp-net-5-mvc6-dependency-injection-in-6-steps/

https://codewala.net/2015/04/30/your-dependency-injection-ready-asp-net-asp-net-5/

这是官方文档的链接:

https://docs.asp.net/en/latest/fundamentals/dependency-injection.html#service-lifetimes-and-registration-options

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

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

 public MyConsumingClass(IDependency dependency) 

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

当必须注入多个相同类型的对象时,瞬态,作用域和单例定义ASP.NET MVC核心DI中的对象创建过程。 如果您不熟悉dependency injection,您可以看到这个DI IOCvideo

您可以看到下面的控制器代码,其中我在构造函数中请求了两个“IDal”实例。 Transient,Scoped和Singleton定义是否在“_dal”和“_dal1”中注入相同的实例或不同。

 public class CustomerController : Controller { IDal dal = null; public CustomerController(IDal _dal ,IDal _dal1) { dal = _dal; // DI of MVC core // inversion of control } } 

瞬态: – 在瞬态新对象实例中将注入一个请求和响应。 下面是我显示GUID值的快照图像。

在此处输入图像描述

Scoped: – 在作用域中,相同的对象实例将在单个请求和响应中注入。

在此处输入图像描述

Singleton: – 在Singleton中,将在所有请求和响应中注入相同的对象。 在这种情况下,将创建一个对象的全局实例。

下面是一个简单的图表,它直观地解释了上述基本原理

MVC DI图像

上面的图片由SBSS团队在孟买培训中进行ASP.NET MVC培训时绘制,非常感谢SBSS团队创建上述图像。