Eu quero implementar *injeção de dependência
*** em Asp.Net Core
*. Então, depois de adicionar estes códigos ao método ConfigureServices
****, ambas as maneiras funcionam.
Qual é a diferença entre os métodos services.AddTransient
e service.AddScoped
no Asp.Net Core
?
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddScoped<IEmailSender, AuthMessageSender>();
}
**TL;DR***
Os objetos transitórios são sempre diferentes; uma nova instância é fornecida para cada controlador e cada serviço.
Os objetos escopados são os mesmos dentro de um pedido, mas diferentes através diferentes pedidos.
Os objetos de um botão são os mesmos para cada objeto e cada pedido.
Para mais esclarecimentos, este exemplo de asp.net docs mostra a diferença :
Para demonstrar a diferença entre essas opções de vida útil e de registro, considere uma interface simples que represente uma ou mais tarefas como uma operação com um identificador único, `OperationId'. Dependendo de como configuramos a vida útil para este serviço, o container fornecerá as mesmas ou diferentes instâncias do serviço para a classe solicitante. Para deixar claro qual o tempo de vida que está sendo solicitado, criaremos um tipo por opção 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 estas interfaces utilizando uma única classe, 'Operação', que aceita um 'Guia' em seu construtor, ou utiliza um novo 'Guia' 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;
}
}
A seguir, em `ConfigureServices', cada tipo é adicionado ao contentor de acordo com a sua vida útil:
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
services.AddTransient<OperationService, OperationService>();
Note que o serviço IOperationSingletonInstance' está utilizando uma instância específica com um ID conhecido de
Guid.Empty', então ficará claro quando este tipo estiver em uso. Também registramos um OperationService' que depende de cada um dos outros tipos de
Operation', para que fique claro dentro de uma requisição se este serviço está recebendo a mesma instância do controlador, ou uma nova, para cada tipo de operação. Tudo que este serviço faz é expor suas dependências como propriedades, para que elas possam ser exibidas na visualizaçã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 os tempos de vida dos objetos dentro e entre pedidos individuais separados para a aplicação, a amostra inclui um OperationsController' que solicita cada tipo de
IOperation' assim como um OperationService'. A ação
Index' então exibe todos os valores de OperationId
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 são feitos dois pedidos separados para esta acção do controlador:
Observe qual dos valores de "Operação" varia dentro de uma solicitação, e entre as solicitações.
Os objetos transitórios são sempre diferentes; uma nova instância é fornecida a cada controlador e a cada serviço.
Os objetos escopados são os mesmos dentro de uma solicitação, mas diferentes entre diferentes solicitações
Os objetos Singleton são os mesmos para cada objeto e cada pedido (independentemente de uma instância ser fornecida em `ConfigureServices')
Na injeção de dependência do dotnet há 3 grandes vidas:
**Algum botão*** que cria uma única instância em toda a aplicação. Ele cria a instância pela primeira vez e reutiliza o mesmo objeto em todas as chamadas.
Scoped serviços vitalícios são criados uma vez por pedido dentro do escopo. É equivalente a Singleton no escopo atual. Por exemplo, em MVC ele cria 1 instância por cada solicitação http mas usa a mesma instância nas outras chamadas dentro da mesma solicitação web.
Transient serviços vitalícios são criados cada vez que eles são solicitados. Esta vida útil funciona melhor para serviços leves e sem estado.
Aqui você pode encontrar e exemplos para ver a diferença :
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/
e este é o link para a documentação oficial :
Transiente , scoped e singleton definem o processo de criação de objetos em ASP.NET MVC core DI quando múltiplos objetos do mesmo tipo têm que ser injetados. No caso de você ser novo na injeção de dependência, você pode ver isto [vídeo DI IOC][1].
Você pode ver o código do controlador abaixo no qual eu pedi duas instâncias de "IDal" no construtor. Transient , Scoped e Singleton definem se a mesma instância será injetada em "_dal" e "_dal1" ou diferente.
public class CustomerController : Controller
{
IDal dal = null;
public CustomerController(IDal _dal
,IDal _dal1)
{
dal = _dal;
// DI of MVC core
// inversion of control
}
}
Transiente :- Em casos transitórios, novos objetos serão injetados em uma única solicitação e resposta. Abaixo está uma imagem instantânea onde eu mostrei os valores do GUID.
Scoped :- No scoped mesmo objeto instância será injetado em um único pedido e resposta.
Singleton :- Em Singleton mesmo objeto será injetado em todos os pedidos e respostas. Neste caso, será criada uma instância global do objeto.
Abaixo está um diagrama simples que explica o fundamental visualmente acima.
A imagem acima foi desenhada pela equipe da SBSS quando eu estava fazendo o treinamento ASP.NET MVC em Mumbai , um grande obrigado à equipe da SBSS para criar a imagem acima.