.NET Core - Injeção de dependência (DI)
Neste artigo vamos recordar os conceitos da injeção de dependência no ambiente .NET Core. |
O Net Core suporta o Padrão de injeção de dependência (DI), que é uma técnica para obter a inversão de controle (IoC) entre classes e suas dependências.
E você não precisa de nenhuma biblioteca externa de injeção de dependência para usar este recurso no .NET Core porque ele esta integrado ao .NET Core.
Mas o que é dependência ?
Uma dependência é qualquer outro objeto que é requerido por um objeto.
E o que é Dependency Injection ou injeção de dependência ?
Basicamente, temos
dois princípios importantes para definir a injeção de dependência:
1- “Módulos de alto nível não devem depender de módulos de baixo nível. Ambos
devem depender de abstrações. “
2- “As abstrações não devem depender de detalhes. Os detalhes devem depender de
abstrações. “
Esse é o mantra recitado pela comunidade e encontrado no livro
"Princípios, padrões e práticas ágeis em C#" de Robert C. Martin e
Micah Martin.
Os módulos de alto nível são módulos que contém as regras de negócio e os módulos de baixo nível são módulos que contém implementação de infraestrutura.
Aqui, entendemos
'abstração' como interfaces e classes abstratas e por 'detalhes'
entendemos como classes concretas.
Vamos ilustrar com um exemplo.
Vamos supor que temos duas classes :
1- A classe SaudacaoService e a classe Program
Não existe dependência nenhuma entre essas duas classes.
Mas a situação vai mudar de figura se eu precisar saudar alguém e ajustar o código conforme abaixo:
Agora, a classe
Program depende de
SaudacaoService ou em outras palavras,
SaudacaoService é uma dependência da classe Program.
No código estamos instanciando diretamente a classe
SaudacaoService, e, esta abordagem não é uma boa estratégia se pensarmos
em termos de escalabilidade.
Ao fazermos isso,
nosso código se torna DEPENDENTE de outros componentes ou, em outras palavras,
houve um AUMENTO DE ACOPLAMENTO em nosso código.
Devemos evitar essa situação pelos seguintes motivos:
- Para substituir SaudacaoService por uma
implementação diferente, a classe Program tem que
ser modificada;
- Se SaudacaoService tiver muitas dependências,
elas devem ser configuradas pela classe. Além disso, a classe
SaudacaoService é responsável pelo tempo de vida de
suas dependências;
Desta forma usando essa implementação fica difícil fazer testes de unidade
porque nosso código usa classes concretas.
Aqui podemos usar a injeção de dependência para nos ajudar e para ilustrar como este recurso é importante para desacoplar código.
Para poder usar a injeção de dependência temos as seguintes diretrizes:
Então com base nessas premissas vamos ajustar a nossa aplicação para poder usar o recurso da injeção da dependência.
Usando a injeção de dependência(DI)
Nosso primeiro exemplo usando a DI será um aplicativo Net Core Console porque muitas vezes as pessoas pensam que o recurso interno de injeção de dependência pode ser usado apenas em um contexto da WEB (ASP.NET CORE), mas isso não é correto.
Veja a seguir o código modificado :
Neste código criei uma nova interface : ISaudacaoService com uma assinatura de método DizOla() que retorna uma string.
A classe SaudacaoService agora implementa a interface, e, no construtor da classe estamos gerando um Id exclusivo que é atribuído à propriedade Id do tipo Guid.
Instalando o contâiner DI e registrando serviços
Vamos então fazer a injeção da dependência e para isso precisamos instalar o pacote Microsoft.Extensions.DependencyInjection no projeto Console. (Nas aplicações ASP .NET Core isso não é preciso)
Com o contêiner DI
instalado precisamos criar o contêiner e registrar todos os nossos
serviços.
Podemos registrar diferentes tipos de serviços, dependendo de seu TEMPO DE VIDA:
Exemplo de criação de contêiner e registro de serviço:
Aqui criamos o contêiner usando a classe ServiceCollection()
e a seguir registramos o serviço ISaudacaoService
com o tempo de vida Singleton;
Quando registramos nossos serviços, o próximo passo é solicitar os serviços ao container, mas não podemos fazer isso diretamente, precisamos solicitar o container através do Provedor. Veja um exemplo de código que faz isso:
Neste código solicitamos ao provedor duas instâncias de ISaudacaoService, mas este serviço está registrado como Singleton no Container e por isso o container deve retornar a mesma instância, ou seja: saudadorA e saudadorB devem ser a mesma instância/objeto.
Além disso, ambas as classes devem ter O MESMO CÓDIGO DE HASH e o construtor deve executar APENAS UMA VEZ.
Resultado obtido :
Percebeu a 'mágica' , o construtor foi chamado apenas uma vez e ambas as classes tem o mesmo código hash porque são a mesma classe.
Vamos agora registrar o serviço usando o tempo de vida Transient e ver o resultado:
services.AddTransient<ISaudacaoService, SaudacaoService>();
Nesse caso, o contêiner deve retornar diferentes instâncias de SaudacaoService porque o tempo de vida Transient gera uma nova instância a cada vez que é solicitado.
Resultado:
Agora o contêiner criou duas instâncias de Saudador
e percebemos que o construtor foi chamado duas vezes e cada instância tem um Id
e um código Hash diferentes.
Para concluir vamos registrar o serviço usando o tempo de vida Scoped :
services.AddScoped<ISaudacaoService,
SaudacaoService>();
Resultado:
Podemos ver como o container retorna o mesmo objeto, mas lembre-se de que isso se aplica apenas a projetos de aplicativos de console.
Em um ambiente da Web, o tempo de vida SCOPED criará instâncias POR REQUEST.
"Os que confiam no SENHOR serão como
o monte de Sião, que não se abala, mas permanece para sempre."
Salmos 125:1
Referências:
ASP .NET Core - Implementando a segurança com
ASP.NET Core MVC - Criando um Dashboard .
C# - Gerando QRCode - Macoratti
ASP .NET - Gerando QRCode com a API do Google
ASP .NET Core 2.1 - Como customizar o Identity
Usando o ASP .NET Core Identity - Macoratti
ASP .NET Core - Apresentando o IdentityServer4
ASP .NET Core 3.1 - Usando Identity de cabo a rabo
ASP .NET Core - Usando a Injeção de dependência nativa
C# - Inversão da Dependência - Macoratti.net
ASP .NET MVC 6 - Usando a Injeção de dependência (DI)
ASP .NET Core - Injeção de Dependência via Método
C# - Injeção de dependência(DI) e Inversão de Controle(IoC)
Inversão de controle e Injeção de dependência para iniciantes
ASP .NET MVC 5 - Implementando a Injeção de dependência