Neste artigo vou mostrar como usar a injeção de dependência(DI) em aplicações ASP .NET MVC 6. (Estou usando a ASP .NET Core 1.0 RC2) |
Tecnicamente falando, DI ou Dependency Injection, é definida como um padrão de projeto de software que implementa a inversão de controle (IoC) para resolver dependências entre objetos.
A dependência é um objeto (ou serviço) o qual é passado como dependência para a aplicação cliente. A utilização deste padrão de projeto faz com que os componentes fiquem fracamente acoplados e pode ser implementado de maneira bem simples.
Funciona assim...
Quando um objeto A deseja acessar métodos de um objeto B, então ao invés de instanciar diretamente o objeto B no objeto A, o objeto B é injetado como uma dependência. Neste caso o objeto B implementa uma interface a qual é passada para o objeto A. Dai, o objeto B não é instanciando usando a palavra chave new no objeto A.
A vantagem dessa abordagem é que se no futuro o objeto B mudar, o objeto A não será afetado diretamente. Temos assim objetos levemente acoplados o que é uma boa prática.
Podemos realizar a injeção de dependência de diversas formas e geralmente usamos um framework como o NUnity ou o Ninject, dentre outros, para realizar a injeção.
A injeção de dependência com ASP .NET Core no MVC 6
A novidade é que com a ASP .NET MVC 6 temos agora um mecanismo nativo para realizar a injeção de dependência sem precisar usar frameworks.(Embora você possa continuar a fazer a DI usando os frameworks)
Nota: Na abordagem ASP .NET MVC 6 um tipo a ser injetado é chamado de um serviço.
A estrutura de injeção de dependência do ASP.NET MVC 6 faz duas tarefas básicas para você:
Há quatro modos de vida para um serviço que está sendo injetado:
Vamos ver como cada um desses modos funcionam na prática em uma aplicação ASP .NET MVC 6.
Recursos usados
Criando o projeto no VS Community 2015
Abra o VS Community 2015 e clique em New Project;
Selecione Visual C# -> Web;
Escolha o template ASP .NET Core Web Application (.NET Core) e informe o nome Mvc6_InjecaoDependencia e clique em OK;
Selecione o template Empty e clique em OK:
Será criada uma solução com estrutura exibida abaixo:
Observe que não temos na estrutura criada as pastas Models, Views e Controllers, e, se precisarmos teremos que criar essas pastas no projeto.
Configurando o ambiente
Se você expandir a guia References do projeto e visualizar o conteúdo do arquivo project.json vai verificar que temos as seguintes referências:
Note que ainda não temos uma referência a biblioteca do MVC e precisamos incluir essa referência.
Abra o arquivo Startup.cs e no método ConfigureServices() digite : services.AddMvc()
A seguir selecione : Add package Microsoft.AspNetCore.Mvc 1.0.0-rc2-final para incluir a referência ao pacote MVC:
Vamos agora criar as pastas Servicos, Controllers Views no projeto:
Para isso selecione o projeto e no menu Project clique em New Folder e informe o nome de cada pasta:
Dentro da pasta Views vamos criar outra pasta chamada Home usando o mesmo procedimento. A final teremos a seguinte estrutura do projeto:
Observe também a referência à biblioteca Mvc no arquivo project.json.
Definindo um serviço para a injeção de dependência (DI)
Vamos definir um serviço bem simples para que possamos mostrar a injeção de dependência na ASP .NET MVC 6.
Vamos criar um serviço para gerar um identificador único universal usando a estrutura Guid e o método NewGuid() para criar uma nova instância da Guid.
Na pasta Servicos inclua uma interface chamada IServicoGuid via menu Project -> Add New Item -> Interface, com o código abaixo:
public interface IServicoGuid
{
string IDUnico { get; set; }
}
|
Nada de mais, definimos apenas uma propriedade chamada IDUnico.
Agora vamos incluir na mesma pasta uma classe chamada ServicoGuid que vai implementar essa interface com o código abaixo:
using System;
namespace Mvc6_InjecaoDependencia.Servicos
{
public class ServicoGuid : IServicoGuid
{
public string IDUnico { get; set; }
public ServicoGuid()
{
this.IDUnico = Guid.NewGuid().ToString();
}
}
}
|
Definimos no construtor da classe a geração do identificador único usando o método NewGuid() e convertendo para string.
Pois bem esse será o serviço que iremos injetar em nossa aplicação ASP .NET MVC 6.
Criando o controlador HomeController
Clique com o botão direito do mouse sobre a pasta Controllers e a seguir em Add New Item;
Selecione a guia ASP .NET e a opção MVC Controller Class e clique no botão Add;
O controlador será criado com o método Action Index() que irá tratar a requisição GET.
Inclua o código abaixo em azul no controlador HomeController :
using Microsoft.AspNetCore.Mvc;
using Mvc6_InjecaoDependencia.Servicos;
namespace Mvc6_InjecaoDependencia.Controllers
{
public class HomeController : Controller
{
private IServicoGuid servico;
public HomeController(IServicoGuid _servico)
{
this.servico = _servico;
}
// GET: /<controller>/
public IActionResult Index()
{
ViewBag.Mensagem = "Usando Injeção de Dependência com ASP .NET MVC 6";
ViewBag.GUID = this.servico;
return View();
}
}
}
|
O código acima define uma variável servico do tipo IServicoGuid e no construtor do controlador temos a injeção da instância do serviço representada por _servico e que iremos configurar mais adiante.
O método Action Index() usa o serviço injetado e obtém o identificado global único gerado.
Agora vamos definir a rota padrão da aplicação no arquivo Startup.cs no interior do método Configure:
public void Configure(IApplicationBuilder app)
{
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
|
Assim a rota padrão define o controlador Home e o método Index para executarem quando a aplicação iniciar.
Criando a View Index.cshtml na pasta Views/Home
Agora clique com o botão direito sobre a pasta Views/Home e a seguir em Add New Item;
Selecione a guia ASP.NET e a opção MVC View Page e clique em Add;
Será criado o arquivo Index.cshtml na pasta Views/Home. Altere o código do arquivo conforme abaixo:
<html>
<head>
<title>Minha Primeira Aplicação ASP .NET MVC 6</title>
</head>
<body>
<h1>Macoratti .net</h1>
<hr />
<h4>@ViewBag.Mensagem</h4>
<br />
<h3>Identificador Global Único Gerado : @ViewBag.GUID.IDUnico</h3>
</body>
</html>
|
Esta view vai exibir o resultado do serviço criado.
Aplicando a injeção de dependência
Para realizar o mapeamento das dependências a serem resolvidas precisamos informar qual a interface e a respectiva classe definidas para o nosso serviço.
Isso é feito no método ConfigureServices da classe Startup onde vamos incluir o código a seguir:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
//services.AddScoped<IServicoGuid, ServicoGuid>();
//services.AddTransient<IServicoGuid, ServicoGuid>();
services.AddSingleton<IServicoGuid, ServicoGuid>();
}
|
Note que estamos injetando o serviço usando os modos de vida Singleton, Scoped e Transient.
A classe ConfigureServices() recebe como parâmetro uma referência do tipo IServiceCollection que será usada para especificar as dependências do projeto.
No nosso exemplo será registrada a classe ServicoGuid como um tipo de serviço.
1- Usando o modo Singleton
Vamos iniciar testando o AddSingleton que vai registrar o serviço usando o modo Singleton e a seguir os demais tipos de modo de vida do serviço.
Se executarmos agora nosso projeto iremos obter o seguinte resultado :
Se você abrir outra guia do navegador e acionar a URL localhost:1894 vai obter o mesmo resultado confirmando que o objeto Singleton esta sendo criado.
2- Usando o modo Scoped
No método ConfigureServices da classe Startup altere o código conforme abaixo:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddScoped<IServicoGuid, ServicoGuid>();
//services.AddTransient<IServicoGuid, ServicoGuid>();
//services.AddSingleton<IServicoGuid, ServicoGuid>();
}
|
Agora estamos usando o modo Scoped.
Executando o projeto em diversas instâncias do navegador iremos obter o seguinte resultado:
Observe que para cada instância obtemos um número diferente para o Guid o que indica que cada requisição esta sendo fornecida por uma nova instância do objeto.
3- Usando o modo Transient
No método ConfigureServices da classe Startup altere o código conforme abaixo:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
// services.AddScoped<IServicoGuid, ServicoGuid>();
services.AddTransient<IServicoGuid, ServicoGuid>();
//services.AddSingleton<IServicoGuid, ServicoGuid>();
}
|
Agora estamos usando o modo Transient.
Para simular a múltipla criação de objetos em um único ciclo request-response vamos alterar o código do controlador HomeController conforme a seguir:
public class HomeController : Controller
{
private IServicoGuid servico1;
private IServicoGuid servico2;
public HomeController(IServicoGuid _servico1, IServicoGuid _servico2)
{
this.servico1 = _servico1;
this.servico2 = _servico2;
}
// GET: /<controller>/
public IActionResult Index()
{
ViewBag.Mensagem = "Usando Injeção de Dependência com ASP .NET MVC 6";
ViewBag.GUID1 = this.servico1;
ViewBag.GUID2 = this.servico2;
return View();
}
}
|
Precisamos alterar também a view Index.cshtml para exibir o resultado conforme o código abaixo:
<html>
<head>
<title>Minha Primeira Aplicação ASP .NET MVC 6</title>
</head>
<body>
<h1>Macoratti .net</h1>
<hr />
<h4>@ViewBag.Mensagem</h4>
<br />
<h3> Serviço 1 - Identificador Global Único Gerado : @ViewBag.GUID1.IDUnico</h3>
<h3> Serviço 2 - Identificador Global Único Gerado : @ViewBag.GUID2.IDUnico</h3>
</body>
</html>
|
Executando o projeto novamente teremos :
4- Usando o modo Instance
Neste modo temos que criar uma instância do serviço ServicoGuid e fazer o registro com o framework DI.
Para fazer isso altere o código do método ConfigureServices() da classe startup.cs conforme abaixo:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
//services.AddScoped<IServicoGuid, ServicoGuid>();
//services.AddTransient<IServicoGuid, ServicoGuid>();
//services.AddSingleton<IServicoGuid, ServicoGuid>();
ServicoGuid obj = new ServicoGuid();
obj.IDUnico = "013f98e7-bb8b-4d9f-b5a0-04e930db88457";
services.AddInstance<IServicoGuid>(obj);
}
|
Criamos um objeto de ServicoGuid e atribuímos à sua propriedade IDUnico um valor. Assim criamos manualmente uma instância do objeto e então registramos usando o método AddInstance().
Executando o projeto com os ajustes na View veremos que ele se comporta como o modo Singleton.
Dessa forma vimos como realizar a injeção de dependência usando os recursos nativos da ASP .NET MVC 6.
Pegue o projeto completo aqui : Mvc6_InjecaoDependencia.zip
Aquele que nem mesmo a seu próprio Filho
poupou, antes o entregou por todos nós, como nos não dará também com ele todas
as coisas?
Romanos 8:32
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
Curso Fundamentos da Programação Orientada a Objetos com VB .NET
NET - Inversão de controle e Injeção de dependência ... - Maco
.NET - Inversão de Controle (IoC) e Injenção de Dependência (DI