AddTransient, AddScoped en AddSingleton Services Verschillen?

Ik wil dependency injection implementeren in Asp.Net Core. Dus na het toevoegen van deze codes aan ConfigureServices methode, werken beide manieren.

Wat is het verschil tussen services.AddTransient en service.AddScoped methodes in Asp.Net Core?

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

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

TL;DR

Transient objecten zijn altijd anders; een nieuwe instantie wordt verstrekt aan

elke controller en elke service.

Scoped objects zijn hetzelfde binnen een request, maar verschillend over verschillende requests.

Singleton objecten zijn hetzelfde voor elk object en elk request.

Voor meer verduidelijking, dit voorbeeld uit asp.net docs toont het verschil :

Om het verschil tussen deze levensduur en registratie opties te demonstreren, beschouwen we een eenvoudige interface die een of meer taken vertegenwoordigt als een operatie met een unieke identifier, OperationId. Afhankelijk van hoe we de levensduur voor deze service configureren, zal de container dezelfde of verschillende instanties van de service leveren aan de aanvragende klasse. Om duidelijk te maken welke levensduur wordt aangevraagd, maken we een type per levensduur optie:

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
    {
    }
}

We implementeren deze interfaces met behulp van een enkele klasse, Operation, die een Guid accepteert in zijn constructor, of een nieuwe Guid gebruikt als er geen is opgegeven:

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;
    }
}

Vervolgens wordt in ConfigureServices, elk type aan de container toegevoegd volgens zijn benoemde levensduur:

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

Merk op dat de IOperationSingletonInstance service een specifieke instantie gebruikt met een bekende ID van Guid.Empty zodat het duidelijk is wanneer dit type in gebruik is. We hebben ook een OperationService geregistreerd die afhankelijk is van elk van de andere Operation types, zodat het binnen een request duidelijk is of deze service dezelfde instantie krijgt als de controller, of een nieuwe, voor elk operation type. Het enige wat deze service doet is zijn afhankelijkheden blootstellen als eigenschappen, zodat ze kunnen worden weergegeven in de view.

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;
        }
    }
}

Om de levensduur van objecten binnen en tussen afzonderlijke verzoeken aan de applicatie te demonstreren, bevat het voorbeeld een OperationsController die elk soort IOperation type aanvraagt, evenals een OperationService. De Index actie toont dan alle OperationId waarden van de controller en de service.

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();
        }
    }
}

Nu worden er twee afzonderlijke verzoeken gedaan aan deze controller actie:

Kijk welke van de OperationId waarden varieert binnen een request, en tussen requests.

  • Transient objecten zijn altijd verschillend; een nieuwe instantie wordt aan elke controller en elke service verstrekt.

  • Scoped objecten zijn hetzelfde binnen een verzoek, maar verschillend tussen verschillende verzoeken

  • Singleton objecten zijn hetzelfde voor elk object en elk verzoek (ongeacht of een instantie is verstrekt in ConfigureServices)

Commentaren (15)

In dotnet's dependency injection zijn er 3 grote lifetimes :

Singleton die een enkele instantie creëert in de hele applicatie. Het creëert de instantie voor de eerste keer en hergebruikt hetzelfde object in alle aanroepen.

Scoped lifetime services worden eenmaal per aanvraag binnen het bereik aangemaakt. Het is gelijkwaardig aan Singleton in het huidige bereik. bv. in MVC maakt het 1 instantie per http verzoek, maar gebruikt dezelfde instantie in de andere aanroepen binnen hetzelfde web verzoek.

Transient lifetime services worden aangemaakt elke keer dat ze worden opgevraagd. Deze levensduur werkt het beste voor lichtgewicht, stateless services.

Hier kun je voorbeelden vinden om het verschil te zien:

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/

en dit is de link naar de officiële documentatie :

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

Commentaren (7)

Transient , scoped en singleton definiëren object creatie proces in ASP.NET MVC core DI wanneer meerdere objecten van hetzelfde type moeten worden geïnjecteerd. In het geval dat je nieuw bent met Dependency injection kun je deze [DI IOC video][1] bekijken.

Je kunt de onderstaande controller code zien waarin ik twee instanties van "IDal" heb opgevraagd in de constructor. Transient , Scoped en Singleton definiëren of dezelfde instantie zal worden geïnjecteerd in "_dal" en "_dal1" of verschillend.

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

Transient :- In transient worden nieuwe object instanties geïnjecteerd in een enkel Request en response. Hieronder is een snapshot afbeelding waar ik GUID waarden heb weergegeven.

Scoped :- In scoped zal dezelfde object instantie worden geïnjecteerd in een enkel verzoek en antwoord.

Singleton :- In Singleton zal hetzelfde object worden geïnjecteerd over alle request en response. In dit geval zal een globale instantie van het object worden gecreëerd.

Hieronder is een eenvoudig diagram dat het bovenstaande fundament visueel uitlegt.

De bovenstaande afbeelding is getekend door het SBSS team toen ik de ASP.NET MVC training in mumbai training volgde, met grote dank aan het SBSS team voor het maken van de bovenstaande afbeelding.

Commentaren (2)