.NET Core — Dependency Injection

Nelson Souza
4 min readAug 21, 2019

--

Exemplificando Singleton / Scoped / Transient

Olá tudo bem? Sabemos que por padrão o .NET Core trás uma interface que injeta das dependências de forma simples e amigável. No entanto, muitas vezes, não sabemos como usar de forma correta. Neste post, vou tentar exemplificar o uso dos 3 tipos de registro de dependências: Singleton, Scoped e Transient.

Vida útil de um serviço

Quando registramos um serviço, somos nós quem decidimos qual será a vida útil dele. Definir a vida útil, quer dizer que saberemos quantas vezes um componente é instanciado e se um componente é compartilhado. E no .NET Core existem 3 opções para isso:

Singleton
Significa que apenas uma única instância será criada. Essa instância é compartilhada entre todos os componentes que exigem isso. A mesma instância é, portanto, usada sempre.

Scoped
Uma instância é criada uma vez por escopo. Um escopo é criado em cada solicitação para o aplicativo (cada pedido é um escopo), portanto, todos os componentes registrados como scoped serão criados uma vez por solicitação.

Transient
Os componentes são criados toda vez que são solicitados e nunca são compartilhados.

IServiceColletion

IServiceColletion é interface responsável por registrar nossos componentes/serviços. Então a partir dela vamos iniciar nossa demo.

Vamos criar um projeto vazio do tipo ASP Net Core Web Application. No projeto vou criar a seguinte estrutura:

Todas as interfaces terão um método que retornarão um Guid. O código fonte estará no final do post.

Na classe Startup, vamos registrar dessa forma:

public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IScopedService, ScopedService>();
services.AddSingleton<ISingletonService, SingletonService>();
services.AddTransient<ITransientService, TransientService>();
}

Na DemoController vamos injetar as interfaces no construtor e criar métodos de Get para cada um dos serviços. Mas antes, vamos também criar uma cópia de cada uma das interfaces, por exemplo:

private readonly IScopedService _scopedService_1;
private readonly IScopedService _scopedService_2;
private readonly ISingletonService _singletonService_1;
private readonly ISingletonService _singletonService_2;
private readonly ITransientService _transientService_1;
private readonly ITransientService _transientService_2;

Desta forma, vamos ver o resultado quando chamamos as 2 instâncias mais de uma vez.

Exibindo resultados

Enfim os resultados quando chamamos 2 vezes a API.

Scoped:
Nos 2 casos chamando a API, a instância 2 reutilizou o que a instância 1 tinha criado.

Singleton:
Uma vez criada a instância 1, todo o resto vai reutilizar. Não houve uma nova criação de valores na segunda chamada da API.

Transient:
Por fim, vemos que nas duas chamadas à API, cada instância criou seus próprios valores.

Conclusão

Já sabe qual usar? Vamos a alguns exemplos:

  • Scoped: Se quiser manter o estado do serviço em um request. Eles só irão mudar sempre quando fizer um novo request.
  • Singleton: Onde você precisa reutilizar o serviço em várias pontas de sua aplicação como por exemplo: configurações do aplicativo ou parâmetros, serviço de log, armazenamento em cache de dados.
  • Transient: Temporário, passageiro como tradução literal. Será criada uma nova instância do objeto toda vez que fizer uma requisição. Mas, uma vez que eles são criados, eles usarão mais memória e recursos, e podem ter o impacto negativo no desempenho. Então use para o serviço leve com pouco ou nenhum estado.

Referências

--

--

Nelson Souza
Nelson Souza

Responses (2)