AddTransient,AddScoped和AddSingleton服务的差异?

自作多情 提交于 2019-12-28 21:10:33

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

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

services.AddTransientservice.AddScoped方法有什么区别是Asp.Net Core

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

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

#1楼

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

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


#2楼

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的特定实例,因此在使用此类型时将清楚。 我们还注册了一个OperationService依赖于每个其他的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中是否提供了实例)


#3楼

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

你可以看到下面的控制器代码,我在构造函数中请求了两个“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值的快照图像。

范围: - 在范围内相同的对象实例将被注入单个请求和响应。

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

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

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


#4楼

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

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

public MyConsumingClass(IDependency dependency)

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


#5楼

如所描述的在这里 (该链接是非常有用的)用一个例子,

接口和具体类型之间的这种映射定义了,每当您请求一种类型的IContryService时,您将获得CountryService的新实例。 在这种情况下,这就是瞬态意味着什么。 您还可以添加单个映射(使用AddSingleton)和作用域映射(使用AddScoped)。 在这种情况下,Scoped意味着作用域为HTTP请求,这也意味着当前请求正在运行时它是一个单例。 您还可以使用AddInstance方法将现有实例添加到DI容器中。 这些是几乎完整的注册IServiceCollection的方法

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!