ASP .NET Core - Injetando um serviço na View (DI)


Neste artigo vamos rever a injeção de dependência na ASP .NET Core e, porque é importante você entender como funciona e como usá-la.

Com o advento da ASP.NET Core, a Injeção de dependência agora é um cidadão de primeira classe na ASP.NET. Todas as partes da pilha ASP.NET estão usando o mesmo contêiner DI. Veremos como configurar e como usar o contâiner DI.

Vamos fazer tudo de uma maneira bem simples. Vamos criar um serviço que fornece uma lista de Produtos e uma interface para este serviço. A seguir veremos como usar o serviço via DI.

Recursos Usados:

Criando o projeto ASP .NET Core e o serviço

Podemos criar o projeto usando o Visual Studio Community ou o a ferramenta de linha de comando Net CLI e o editor Visual Studio Code.

Vamos de linha de comando...

Crie uma pasta onde o projeto será armazeando e a partir desta pasta abra um prompt de comandos e digite : dotnet new mvc

Abra o projeto no VS Code digitando na linha de comando : code .

Crie uma pasta chamada Models e crie a classe Produto nesta pasta com o código abaixo:

    public class Produto
    {
        public string Codigo { get; internal set; } 
        public string Nome { get; internal set; } 
    }

Crie uma pasta chamada Services e crie uma interface chamada IProdutoService com o código a seguir:

using aspncoredi.Models;
namespace aspncoredi.Services
{
    public interface IProdutoService
    {
         IEnumerable<Produto> GetProdutos(); 
    }
}

Ainda nesta pasta crie a classe ProdutoService que implementa esta interface :

using System.Collections.Generic;
using aspncoredi.Models;
namespace aspncoredi.Services
{
    public class ProdutoService : IProdutoService
    {
        public IEnumerable<Produto> GetProdutos()
        {
            return new List<Produto> 
            { 
                new Produto {Codigo = "CAD01", Nome = "Caderno" }, 
                new Produto {Codigo = "CAN01", Nome = "Caneta" }, 
                new Produto {Codigo = "BOR01", Nome = "Borracha" }, 
                new Produto {Codigo = "LAP01", Nome = "Lápis" }, 
                new Produto {Codigo = "APO01", Nome = "Apontador" } , 
                new Produto {Codigo = "EST01", Nome = "Estojo" }
            }; 
        }
    }
}

Pronto temos o nosso serviço e interface prontos para uso.

Registrando o serviço

Precisamos agora adicionar o serviço ProdutoService ao contâiner de injeção de dependência da ASP .NET Core.

Fazemos isso no método ConfigureServices da classe Startup:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddTransient<IProdutoService, ProdutoService>();
            services.AddMvc();
        }

Este mapeamento entre a interface e o seu tipo concreto define que toda a vez que você solicitar um tipo IProdutoService você vai receber uma nova instância de ProdutoService.

Na implementação da Injeção de dependência do ASP.NET Core, vemos o conceito de lifetimes ou "tempo de vidas". Um lifetime ou tempo de vida especifica quando um objeto DI-injetado é criado ou recriado. Existem três possibilidades:

  1. - Transient : Criado a cada vez que são solicitados.
  2. - Scoped: Criado uma vez por solicitação.
  3. - Singleton: Criado na primeira vez que são solicitados. Cada solicitação subseqüente usa a instância que foi criada na primeira vez.

O parâmetro IServiceCollection permite configurar diferentes tipos de serviços, seja por criação de objeto ou correspondência a uma interface específica, e suporta os lifetimes mencionados.

Podemos também adicionar uma instância existente ao contêiner DI usando o método AddInstance.

Se você tiver muitos serviços para registrar, você pode criar um método de extensão para IServiceCollection e assim manter o código da classe Startup mais enxuto. O mesmo é usado por padrão para MVC e muitas outras ferramentas que você deseja usar em seu projeto.

Agora já podemos requisitar uma instância de um ProdutoService em quase todos os locais em nossa aplicação ASP .NET Core MVC.

Usando o serviço

Vamos usar o serviço em um controlador.

Como nosso projeto MVC já tem o controlador HomeController criado por padrão na pasta Controller.

Vamos alterar o seu código conforme mostrado a seguir:

    public class HomeController : Controller
    {
         private readonly IProdutoService _produtoService; 
         public HomeController(IProdutoService produtoService) 
         { 
             _produtoService = produtoService; 
         } 
         public IActionResult Index()
         {
            var produtos = _produtoService.GetProdutos();
            return View(produtos);
         }
          ...
   }

Estamos injetando o serviço no construtor do controlador e usando a instância do serviço para obter os produtos e exibindo-os na view Index.

Abaixo temos o código alterado da view Index.cshtml da pasta Views/Home:

@model IEnumerable<Produto>
<h2>Produtos</h2>
<table border="1" style="width:100%" >
    <tr>
        <th>Código</th>
        <th>Nome</th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>@Html.DisplayFor(modelItem => item.Codigo)</td>
            <td>@Html.DisplayFor(modelItem => item.Nome)</td>
        </tr>
    }
</table>

Após isso digite : dotnet build para verificar se existem erros.

Executando o projeto ( dotnet run )  e acessando localhost:5000 iremos obter:

Injetando o serviço em uma View

Podemos também injetar um serviço em uma view MVC usando a diretiva @inject.

Para o nosso projeto podemos usar:

@inject aspncoredi.Services.IProdutoService ProdutoService;

A primeira parte depois da diretiva @inject define a interface e a segunda parte é o nome da variável que vai tratar a nossa instância.

A sintaxe básica usada é :   @inject <serviço>  <nome>

Onde :
  1. @inject - é a diretiva usada para injetar dependências;
  2. <serviço> - é a classe de serviço;
  3. <nome> - é o nome da injeção do serviço pelo qual poderemos acessar os métodos do serviço;

A título de teste vamos abrir o arquivo About.cshtml da pasta /Views/Home e incluir o código abaixo neste arquivo:

@inject aspncoredi.Services.IProdutoService ProdutoService;
<h1>Macoratti .net - View Injection </h1>
<hr />
<h3>Lista de Produtos</h3>
<ul>
    @foreach (var produto in ProdutoService.GetProdutos())
    {
        <li>@produto.Nome (@produto.Codigo)</li>
    }
</ul>

Neste exemplo estou injetando o serviço ProdutoService que será identificado pelo nome ProdutoService.

A seguir usando um laço foreach acesso o serviço e exibo os nomes de cada produto da lista.

Abaixo vemos o resultado: (dotnet run)

Dessa forma apresentamos o recurso da DI no contâiner ASP .NET Core , seu registro e sua utilização.

Você pode usar DI quase em todos os lugares da sua aplicação (exceto em HtmlHelpers, porque eles são métodos de extensão).

Você pode usar todos os serviços registrados em IServiceCollection, mesmo os serviços registrados pelo ASP.NET Core.

Pegue projeto aqui : aspncoredi.zip

(disse Jesus) 'Todavia digo-vos a verdade, que vos convém que eu vá; porque, se eu não for, o Consolador não virá a vós; mas, quando eu for, vo-lo enviarei.'
João 16:7

Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti