Inversão de controle e injeção de dependência no .net core

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Já falamos sobre injeção de dependência e inversão de controle por aqui anteriormente, sendo que falamos de dois dos muitos containers disponíveis para .net, o Autofac, que é um dos mais utilizados e conhecidos, e do DryIoC, que apesar de não ser tão famoso, é muito leve e rápido. E hoje vamos ver como utilizar a injeção de dependência no .net core, que agora traz um container nativo, não necessitando mais que você adicione um em seu projeto. Apesar de vir com um container nativo, o .net core permite que você troque o container por um de sua preferência caso queira, como por exemplo o Autofac, e essa troca e simples e fácil, mas veremos isso em outro post.

Então vamos colocar a mão na massa e ver como é fácil utilizar DI no .net core. Crie uma Console App (.NET Core) no Visual Studio 2017, e de o nome de DemoDI. Agora vamos criar um interface com o nome ICalculo com o seguinte código:

namespace DemoDI
{
    public interface ICalculo
    {
        double Calcular(double a, double b);
    }
}

Agora vamos criar uma classe para implementar nossa interface, e vamos chamá-la de Soma:

namespace DemoDI
{
    public class Soma : ICalculo
    {
        public double Calcular(double a, double b) => a + b;
    }
}

Agora vamos criar outra classe que implemente a interface ICalculo, e vamos chamá-la de Subtracao:

namespace DemoDI
{
    public class Subtracao : ICalculo
    {
        public double Calcular(double a, double b) => a - b;
    }
}

Agora vamos criar uma classe chamada Calculadora, que receberá uma lista de objetos que implementem a interface ICalculo como parâmetro no construtor, e executará os cálculo com os valores informados para cada objeto recebido, o seu código ficará dessa forma:

using System;
using System.Collections.Generic;

namespace DemoDI
{
    public class Calculadora
    {
        private readonly IEnumerable<ICalculo> calculos;

        public Calculadora(IEnumerable<ICalculo> calculos)
        {
            this.calculos = calculos;
        }

        public void EfetuarCalculo(double a, double b)
        {
            foreach (var calculo in calculos)
            {
                var result = calculo.Calcular(a, b);
                Console.WriteLine($"Resultado: {result}");
            }
        }
    }
}

Agora precisamos adicionar o pacote de injeção de dependência em nosso projeto, para isso digite o comando abaixo no console do Nuget:

Install-Package Microsoft.Extensions.DependencyInjection

Agora temos acesso às classes do container em nosso projeto, e vamos alterar a classe Program, para criarmos nosso container, e utilizarmos nossos objetos. A primeira coisa que iremos fazer é criar nosso container e registrar as classes que criamos, para isso adicione as linhas abaixo dentro do método Main:

IServiceCollection collection = new ServiceCollection();
collection.AddTransient<ICalculo, Soma>();
collection.AddTransient<ICalculo, Subtracao>();
collection.AddSingleton<Calculadora>();
IServiceProvider serviceProvider = collection.BuildServiceProvider();

O que fizemos aqui foi primeiro criar um IServiceCollection, que é quem nos permite registrar nossas classes, depois registramos nossas classes Soma e Subtracao, para serem utilizadas quando um objeto do tipo ICalculo for solicitado, e para isso utilizamos o método AddTransient, que faz com que a cada solicitação, seja criado um novo objeto. Depois registramos nossa classe Calculadora, que não possui interface, então ela será devolvida toda vez que alguém solicitar diretamente pela classe, e como fizemos seu registro utilizando o método AddSingleton, nossa classe será criada apenas uma vez, e sempre que alguém solicitá-la, a mesma cópia será devolvida. E por fim, na última linha, criamos um objeto do tipo IServiceProvider, que é nosso container, sendo ele o responsável por fornecer os objetos toda vez que for solicitado.

Agora vamos pedir ao container que nos forneça um objeto do tipo Calculadora, para isso faremos o seguinte:

Calculadora calculadora = serviceProvider.GetService<Calculadora>();

Sempre que quisermos pedir um objeto ao container, nós utilizamos o método GetService, informando o tipo desejado e o container irá nos fornecer.

Agora vamos efetuar um cálculo e ver o que acontece? Então adicione a linha abaixo:

calculadora.EfetuarCalculo(10, 20);

E por fim, adicione também a linha:

Console.Read();

Rode a aplicação e você verá no console a informação abaixo:

Resultado: 30
Resultado: -10

Veja que nossa calculadora efetuou uma soma e uma subtração com os valores que informamos, agora, como isso ocorreu, se em momento nenhum informamos na sua criação a lista de objetos do tipo ICalculo. A lista foi injetada pelo construtor da classe, pois recebe um IEnumerable<ICalculo>. Como temos registrado mais de uma classe que implementa uma interface, ao pedir para o container um IEnumerable<ICalculo> ele vai nos devolver todos objetos que implementem a interafce, e fazer a injeção.

Lembrando que é uma boa prática a injeção de dependência através de construtores, e sempre que possível deve ser utilizada, evitando a chamada ao container de forma explícita como fizemos para criar a calculadora dentro da função Main, mas vão ter situações que a chamada explícita fará sentido, por isso mostramos aqui. Um dos motivos da injeção via construtores ser recomendada, é por facilitar a criação de testes.

O código completo da classe Program ficou dessa forma:

using System;
using Microsoft.Extensions.DependencyInjection;

namespace DemoDI
{
    class Program
    {
        static void Main(string[] args)
        {
            IServiceCollection collection = new ServiceCollection();
            collection.AddTransient<ICalculo, Soma>();
            collection.AddTransient<ICalculo, Subtracao>();
            collection.AddSingleton<Calculadora>();
            IServiceProvider serviceProvider = collection.BuildServiceProvider();

            Calculadora calculadora = serviceProvider.GetService<Calculadora>();

            calculadora.EfetuarCalculo(10, 20);
            Console.Read();
        }
    }
}

O código completo da aplicação está disponível no GitHub no endereço: https://github.com/desenvolvedorninja/dotnet-core-di-primeiros-passos

Quase 20 anos de experiência no mercado de TI.
Atuação em grandes empresas como Netshoes, Borland, JBS, Bradesco, Hospital das Clínicas, Rede, Prodam, HSPE, Instituto Ayrton Senna, e também em empresas internacionais como Delta Dental, T-Mobile, Pepsi e Mckesson.
Fundador da TecPrime Solutions, administrador da comunidade nopCommerce Brasil, e autor dos sites InvestFacil.net e Desenvolvedores.ninja

Facebooktwittergoogle_plusredditpinterestlinkedinmail

3 thoughts on “Inversão de controle e injeção de dependência no .net core

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *