C# -
Dependency Injection via Console .NET Core - III
![]() |
Neste artigo veremos realizar a injeção de dependência em uma aplicação Console .NET Core usando o contêiner nativo da ASP .NET Core e vamos abordar outros recursos disponíveis. |
Na segunda parte do artigo vimos os tempos de vidas dos serviços criados para injeção de dependência usando o contêiner nativo da ASP .NET Core.
Veremos agora outros recursos disponíveis que podemos usar com o contêiner nativo com exemplos sobre IServiceCollection e IServiceProvider para entender melhor como o mecanismo da injeção de dependência da ASP.NET Core funciona.
Vamos agora mostrar esses recursos, e para começar, crie um projeto Console do tipo .NET Core no VS 2019 ou no VS Code.
A seguir inclua o seguinte pacote no seu projeto: Microsoft.Extensions.DependencyInjection.
Pronto, a seguir vamos usar o projeto criado.
1- Registro de Instância
Podemos criar uma instância de um objeto antes de resgistrar a instância.
Vamos criar primeira a classe MinhaInstancia com uma propriedade Valor:
public class MinhaInstancia { public int Valor { get; set; } } |
Agora vamos definir o código abaixo na classe Program :
using Microsoft.Extensions.DependencyInjection; using System; private static void RegistroInstanciaDemo()
{
var instancia = new MinhaInstancia { Valor = 44 };
IServiceCollection services = new ServiceCollection();
services.AddSingleton(instancia);
foreach (ServiceDescriptor service in services)
{
if (service.ServiceType == typeof(MinhaInstancia))
{
var instanciaRegistrada = (MinhaInstancia)service.ImplementationInstance;
Console.WriteLine("Instância Registrada : " + instanciaRegistrada.Valor);
}
}
var serviceProvider = services.BuildServiceProvider();
var minhaInstancia = serviceProvider.GetService<MinhaInstancia>();
Console.WriteLine("Serviço Registrado pelo registro de instância : " + minhaInstancia.Valor);
}
|
Neste código, primeiro, criamos um novo objeto da classe MinhaInstancia atribuindo o valor de 44 à propriedade Valor, antes de registrá-lo no contêiner DI.
Depois registramos a instância criada e a criamos um serviço usndo BuildServiceProvider().
A seguir resolvemos a instância registrada usando os métodos service.Implementation e serviceProvider.GetInstance.
O resultado obtido é visto a seguir:
2- Registro de tipo genérico
Talvez um dos melhores recursos seja o registro de tipo genérico.
Suponha que você tenha um repositório genérico. Se quisermos registrar este repositório para todos os tipos de DI, tínhamos que registrar todos os tipos separadamente.
Mas agora, o contêiner nativo da ASP.NET Core oferece o suporte ao registro genérico. Vejamos como ele funciona.
Vamos criar uma interface IGenericRepository<T> que simula um repositório genérico:
public interface IGenericRepository<T> { public void Add(T obj); } } |
E a seguir a classe GenericRepository<T> que implementa esta interface:
public class GenericRepository<T> : IGenericRepository<T> where T : class { public void Add(T obj) { Console.WriteLine("Adicionando objeto"); } } |
Vamos criar uma classe Cliente que vamos usar para especializar o nosso repositório:
public class Cliente { public string Nome { get; set; } } |
Agora na classe Program vejamos como fazer o registro do repositório genérico:
private static void RegistroGenerico()
{
Cliente cli = new Cliente();
cli.Nome = "Macoratti";
IServiceCollection services = new ServiceCollection();
services.AddTransient(typeof(IGenericRepository<>), typeof(GenericRepository<>));
var serviceProvider = services.BuildServiceProvider();
var servico = serviceProvider.GetService<IGenericRepository<Cliente>>();
servico.Add(cli);
}
|
Neste código registramos a interface genérica usando typeof, e, como não informamos o tipo (T) ele será resolvido durante a execução do programa como vemos o código que segue.
3- Múltiplos registros
Agora veremos o cenário onde temos uma interface que é implementada por mais de uma classe.
Vamos criar a interface IServico e as classes ServicoA e ServicoB que implementam esta interface em uma pasta Services no projeto:
1- IServico
public interface IServico { string Servico(); } |
2- ServicoA
public class ServicoA : IServico
{
public string Servico()
{
return "ServicoA";
}
}
|
3- ServicoB
public class ServicoB : IServico { public string Servico() { return "ServicoB"; } } |
Agora vejamos como fazer o registro neste cenário:
private static void MultiploRegistro()
{
IServiceCollection servicos = new ServiceCollection();
servicos.AddTransient<IServico, ServicoA>();
servicos.AddTransient<IServico, ServicoB>();
var serviceProvider = servicos.BuildServiceProvider();
var meusServicos = serviceProvider.GetServices<IServico>().ToList();
var meuServico = serviceProvider.GetService<IServico>();
Console.WriteLine("----- Serviços -----------");
foreach (var servico in meusServicos)
{
Console.WriteLine(servico.Servico());
}
Console.WriteLine("----- Serviço ------------");
Console.WriteLine(meuServico.Servico());
}
|
Registramos cada serviço indicando a interface e sua respectiva classe concreta e a seguir podemos obter a lista de serviços e o último registro registrado:
Poderíamos também definir a chamada do serviço com base em uma chave usando um delegate Func:
private static void MultiploRegistro2() { IServiceCollection servicos = new ServiceCollection(); servicos.AddTransient<IServico, ServicoA>();
servicos.AddTransient<IServico, ServicoB>();
servicos.AddTransient<Func<string, IServico>>(servicos => key =>
{
switch (key)
{
case "A":
return servicos.GetService<ServicoA>();
case "B":
return servicos.GetService<ServicoB>();
default:
return null;
}
});
}
|
Na implementação podemos criar um delegate Func<string, IServico> servicoLocator e injetar esse serviço no construtor da classe que desejamos usar para a seguir usar a instância do serviço : servicoLocator("A").Servico();
E estamos conversados...
Pegue o projeto
aqui:
Console_DI_Recursos.zip
"E nós conhecemos, e cremos no amor que Deus nos tem. Deus
é amor; e quem está em amor está em Deus, e Deus nele."
1 João 4:16
Referências: