your programing

AddTransient, AddScoped 및 AddSingleton 서비스 차이점?

lovepro 2020. 9. 30. 11:09
반응형

AddTransient, AddScoped 및 AddSingleton 서비스 차이점?


제가 구현하려는 dependency injection에서 Asp.Net Core. 따라서이 코드를 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>();
}

TL; DR

일시적인 개체는 항상 다릅니다. 모든 컨트롤러와 모든 서비스에 새 인스턴스가 제공됩니다.

범위가 지정된 개체는 요청 내에서 동일하지만 요청에 따라 다릅니다.

Singleton 객체는 모든 객체와 모든 요청에 ​​대해 동일합니다.

더 명확히하기 위해 asp.net 문서 의이 예제 는 차이점을 보여줍니다.

이러한 수명 옵션과 등록 옵션의 차이를 보여주기 위해 하나 이상의 작업을 고유 식별자가있는 작업으로 나타내는 간단한 인터페이스를 고려하십시오 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
    {
    }
}

우리 는 생성자에서 Operationa를 받아들이 Guid거나 Guid아무것도 제공되지 않으면 new를 사용하는 단일 클래스를 사용하여 이러한 인터페이스를 구현합니다 .

using System;
using DependencyInjectionSample.Interfaces;
namespace DependencyInjectionSample.Classes
{
    public class Operation : IOperationTransient, IOperationScoped, IOperationSingleton, IOperationSingletonInstance
    {
        Guid _guid;
        public Operation() : this(Guid.NewGuid())
        {

        }
        public Operation(Guid guid)
        {
            _guid = guid;
        }

        public Guid OperationId => _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).


dotnet의 종속성 주입에는 세 가지 주요 수명이 있습니다.

애플리케이션 전체에 단일 인스턴스를 생성하는 싱글 . 처음으로 인스턴스를 생성하고 모든 호출에서 동일한 객체를 재사용합니다.

범위 내에서 요청 당 한 번씩 범위가 지정된 수명 서비스가 생성됩니다. 현재 범위에서 Singleton과 동일합니다. 예. MVC에서는 각 http 요청 당 1 개의 인스턴스를 생성하지만 동일한 웹 요청 내의 다른 호출에서 동일한 인스턴스를 사용합니다.

임시 수명 서비스는 요청할 때마다 생성됩니다. 이 수명은 경량의 상태 비 저장 서비스에 가장 적합합니다.

여기에서 차이점을 확인할 수있는 예제를 찾을 수 있습니다.

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은 응용 프로그램 도메인의 수명 동안 단일 인스턴스입니다.
  • 범위는 범위가 지정된 요청 기간 동안 단일 인스턴스로, 이는 ASP.NET의 HTTP 요청 당을 의미 합니다.
  • Transient는 코드 요청 당 단일 인스턴스입니다 .

일반적으로 코드 요청은 다음과 같이 생성자 매개 변수를 통해 이루어져야합니다.

public MyConsumingClass(IDependency dependency)

@akazemis의 답변에서 DI의 맥락에서 "서비스"는 RESTful 서비스를 의미하지 않는다는 점을 지적하고 싶었습니다. 서비스는 기능을 제공하는 종속성의 구현입니다.


Transient, scoped 및 singleton은 동일한 유형의 여러 개체를 삽입해야하는 경우 ASP.NET MVC 코어 DI에서 개체 생성 프로세스를 정의합니다. Dependency injection을 처음 사용하는 경우이 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에서는 모든 요청과 응답에 동일한 객체가 주입됩니다. 이 경우 개체의 전역 인스턴스 하나가 생성됩니다.

아래는 위의 기본 사항을 시각적으로 설명하는 간단한 다이어그램입니다.

MVC DI 이미지

The above Image was drawn by SBSS team when i was taking ASP.NET MVC training in mumbai training , a big thanks to SBSS team to create the above image.


AddSingleton()

AddSingleton() creates a single instance of the service when it is first requested and reuses that same instance in all the places where that service is needed.

AddScoped()

In scoped service with every http request we get a new instance. However, with in the same http request if the service is required in multiple places like in the view and in the controller then the same instance is provided for the entire scope of that http request. But every new http request will get a new instance of the service.

AddTransient()

With a transient service a new instance is provided every time a service instance is requested whether it is in the scope of the same http request or across different http requests.


After looking for an answer for this question I found a brilliant explanation with an example that I would like to share with you.

You can watch a video that demonstrate the differences HERE

In this example we have this given code:

public interface IEmployeeRepository
{
    IEnumerable<Employee> GetAllEmployees();
    Employee Add(Employee employee);
}

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class MockEmployeeRepository : IEmployeeRepository
{
    private List<Employee> _employeeList;

    public MockEmployeeRepository()
    {
        _employeeList = new List<Employee>()
    {
        new Employee() { Id = 1, Name = "Mary" },
        new Employee() { Id = 2, Name = "John" },
        new Employee() { Id = 3, Name = "Sam" },
    };
    }

    public Employee Add(Employee employee)
    {
        employee.Id = _employeeList.Max(e => e.Id) + 1;
        _employeeList.Add(employee);
        return employee;
    }

    public IEnumerable<Employee> GetAllEmployees()
    {
        return _employeeList;
    }
}

HomeController

public class HomeController : Controller
{
    private IEmployeeRepository _employeeRepository;

    public HomeController(IEmployeeRepository employeeRepository)
    {
        _employeeRepository = employeeRepository;
    }

    [HttpGet]
    public ViewResult Create()
    {
        return View();
    }

    [HttpPost]
    public IActionResult Create(Employee employee)
    {
        if (ModelState.IsValid)
        {
            Employee newEmployee = _employeeRepository.Add(employee);
        }

        return View();
    }
}

Create View

@model Employee
@inject IEmployeeRepository empRepository

<form asp-controller="home" asp-action="create" method="post">
    <div>
        <label asp-for="Name"></label>
        <div>
            <input asp-for="Name">
        </div>
    </div>

    <div>
        <button type="submit">Create</button>
    </div>

    <div>
        Total Employees Count = @empRepository.GetAllEmployees().Count().ToString()
    </div>
</form>

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddSingleton<IEmployeeRepository, MockEmployeeRepository>();
}

Copy-paste this code and press on the create button in the view and switch between AddSingleton , AddScoped and AddTransient you will get each time a different result that will might help you understand this explanation:

AddSingleton() - As the name implies, AddSingleton() method creates a Singleton service. A Singleton service is created when it is first requested. This same instance is then used by all the subsequent requests. So in general, a Singleton service is created only one time per application and that single instance is used throughout the application life time.

AddTransient() - This method creates a Transient service. A new instance of a Transient service is created each time it is requested.

AddScoped() - This method creates a Scoped service. A new instance of a Scoped service is created once per request within the scope. For example, in a web application it creates 1 instance per each http request but uses the same instance in the other calls within that same web request.


As described here (this link is very useful) with an example,

This mapping between the interface and the concrete type defines, that everytime you request a type of IContryService, you'll get a new instance of the CountryService. This is what transient means in this case. You are also able to add singleton mappings (using AddSingleton) and scoped mappings (using AddScoped). Scoped in this case means scoped to a HTTP request, which also means it is a singleton while the current request is running. You can also add an existing instance to the DI container using the method AddInstance. These are the almost complete ways to register to the IServiceCollection

참고URL : https://stackoverflow.com/questions/38138100/addtransient-addscoped-and-addsingleton-services-differences

반응형