首页 文章

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

提问于
浏览
380

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

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

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

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

4 回答

  • 18

    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<IOperationTransient, Operation>();
    services.AddScoped<IOperationScoped, Operation>();
    services.AddSingleton<IOperationSingleton, Operation>();
    services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
    services.AddTransient<OperationService, OperationService>();
    

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

    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 值中的哪一个 .

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

    • Scoped对象在请求中是相同的,但在不同请求中是不同的

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

  • 223

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

    您可以看到下面的控制器代码,其中我在构造函数中请求了两个“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中,将在所有请求和响应中注入相同的对象 . 在这种情况下,将创建一个对象的全局实例 .

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

    上面的图片由SBSS团队在我接受ASP.NET MVC training in mumbai训练时绘制,非常感谢SBSS团队创建上述图像 .

  • 721

    在dotnet的依赖注入中,有三个主要的生命周期:

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

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

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

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

    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

  • 13
    • Singleton是应用程序域生命周期的单个实例 .

    • Scoped是作用域请求持续时间内的单个实例,这意味着ASP.NET中的每个HTTP请求 .

    • 瞬态是每个代码请求的单个实例 .

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

    public MyConsumingClass(IDependency dependency)
    

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

相关问题