TL; DR
Objetos transitórios são sempre diferentes; uma nova instância é fornecida para todo controlador e todo serviço.
Objetos com escopo definido são os mesmos em uma solicitação, mas diferentes entre solicitações diferentes.
Objetos Singleton são os mesmos para todos os objetos e solicitações.
Para mais esclarecimentos, este exemplo da documentação do ASP.NET mostra a diferença:
Para demonstrar a diferença entre essas opções de duração e registro, considere uma interface simples que represente uma ou mais tarefas como uma operação com um identificador exclusivo OperationId
. Dependendo de como configuramos a vida útil desse serviço, o contêiner fornecerá a mesma ou diferentes instâncias do serviço para a classe solicitante. Para deixar claro qual tempo de vida está sendo solicitado, criaremos um tipo por opção de tempo de vida:
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
{
}
}
Implementamos essas interfaces usando uma única classe, Operation
que aceita um GUID em seu construtor ou usa um novo GUID se nenhum for fornecido:
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;
}
}
Em seguida, em ConfigureServices
, cada tipo é adicionado ao contêiner de acordo com sua vida útil nomeada:
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
services.AddTransient<OperationService, OperationService>();
Observe que o IOperationSingletonInstance
serviço está usando uma instância específica com um ID conhecido de Guid.Empty
, portanto ficará claro quando esse tipo estiver em uso. Também registramos um OperationService
que depende de cada um dos outros Operation
tipos, para que fique claro em uma solicitação se esse serviço está recebendo a mesma instância que o controlador, ou um novo, para cada tipo de operação. Tudo que esse serviço faz é expor suas dependências como propriedades, para que possam ser exibidas na exibição.
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;
}
}
}
Para demonstrar a vida útil do objeto dentro e entre solicitações individuais separadas para o aplicativo, a amostra inclui uma OperationsController
que solicita cada tipo de IOperation
tipo e também uma OperationService
. A Index
ação exibe todos os OperationId
valores do controlador e do serviço .
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();
}
}
}
Agora, dois pedidos separados são feitos para esta ação do controlador:
Observe qual dos OperationId
valores varia dentro de uma solicitação e entre solicitações.
Objetos transitórios são sempre diferentes; uma nova instância é fornecida para todo controlador e todo serviço.
Objetos com escopo definido são os mesmos em uma solicitação, mas diferentes em solicitações diferentes
Objetos Singleton são iguais para todos os objetos e solicitações (independentemente de uma instância ser fornecida em ConfigureServices
)