TL; DR
Les objets transitoires sont toujours différents; une nouvelle instance est fournie à chaque contrôleur et à chaque service.
Les objets étendus sont les mêmes dans une demande, mais différents selon les demandes.
Les objets singleton sont les mêmes pour chaque objet et chaque demande.
Pour plus de précisions, cet exemple de la documentation ASP.NET montre la différence:
Pour démontrer la différence entre ces vie et les options d' enregistrement, pensez à une interface simple qui représente une ou plusieurs tâches comme une opération avec un identifiant unique, OperationId
. Selon la façon dont nous configurons la durée de vie de ce service, le conteneur fournira la même instance ou des instances différentes du service à la classe demandeuse. Pour indiquer clairement quelle durée de vie est demandée, nous allons créer un type par option à vie:
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
{
}
}
Nous implémentons ces interfaces à l'aide d'une seule classe Operation
,, qui accepte un GUID dans son constructeur, ou utilise un nouveau GUID si aucun n'est fourni:
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;
}
}
Ensuite, dans ConfigureServices
, chaque type est ajouté au conteneur en fonction de sa durée de vie nommée:
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
services.AddTransient<OperationService, OperationService>();
Notez que le IOperationSingletonInstance
service utilise une instance spécifique avec un ID connu de Guid.Empty
, il sera donc clair lorsque ce type sera utilisé. Nous avons également enregistré un OperationService
qui dépend de chacun des autres Operation
types, afin qu'il soit clair dans une demande si ce service obtient la même instance que le contrôleur, ou une nouvelle, pour chaque type d'opération. Tout ce service fait est d'exposer ses dépendances en tant que propriétés, afin qu'elles puissent être affichées dans la vue.
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;
}
}
}
Pour illustrer les durées de vie des objets dans et entre des demandes individuelles distinctes à l'application, l'exemple inclut un OperationsController
qui demande chaque type de IOperation
type ainsi qu'un OperationService
. L' Index
action affiche ensuite toutes les OperationId
valeurs du contrôleur et du 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();
}
}
}
Maintenant, deux demandes distinctes sont effectuées pour cette action de contrôleur:
Observez laquelle des OperationId
valeurs varie au sein d'une demande et entre les demandes.
Les objets transitoires sont toujours différents; une nouvelle instance est fournie à chaque contrôleur et à chaque service.
Les objets délimités sont les mêmes dans une demande, mais différents selon les demandes
Les objets singleton sont les mêmes pour chaque objet et chaque demande (indépendamment du fait qu'une instance soit fournie dans ConfigureServices
)