Injeção de Dependência em C# - Parte 1

Olá,

Hoje em dia muito se tem se falado muito em injeção de dependência, principalmente se você desenvolve ou está começando a desenvolver com ASP.NET Core.

Mas que realmente significa “injetar” uma dependência e o que é a tal dependência?

Conceito

Injeção de dependência é um padrão de projeto que permite baixo acoplamento do código!

Ai você se pergunta, mas o que é acoplamento do código? Sendo bem simplista, é um código que possui uma alta dependência de um outro código, onde o relacionamento entre os dois é muito forte!

Por exemplo, você tem uma classe de acesso a banco de dados como o código abaixo:

public class AcessoBanco
{
    SqlConnection _conexao;
    public AcessoBanco(SqlConnection conexao)
    {
        _conexao = conexao;
    }
}

No exemplo acima este código só funciona com SqlConnection! Então se você precisar mudar de banco de dados, terá que reescrever o código.

Agora vamos a um exemplo com baixo acoplamento:

public class AcessoBanco
{
   IDbConnection _conexao;
   public AcessoBanco(IDbConnection conexao)
   {
       _conexao = conexao;
   }
}

Agora estamos implementando IDbConnection, que é a interface implementada pelo SqlConnection. Então temos um código desacoplado do banco, pois qualquer conexão que implemente IDbConnection poderá ser passada para nossa classe!

Este é o princípio da injeção de dependência!

Um exemplo básico de injeção de dependência

Vamos escrever um código bem simples em C# para entendermos como este mecanismo da interface funciona!

Lembre-se que ao referenciar uma Interface você precisa implementar todos os seus métodos!

PS: Somente para tornar mais didático, vou colocar as classes e a interface em um único arquivo, mas em seu projeto coloque-os separadamente!

using System;

public interface IServico
{
    public void Executa();
}

public class ServicoCarro : IServico
{
    public void Executa()
    {
        System.Console.WriteLine("Serviço executado no carro!");  
    }
}

public class ServicoMoto : IServico
{
    public void Executa()
    {
        System.Console.WriteLine("Serviço executado na moto!");
    }
}

Muito bem, temos uma interface IServico que possui um método Executa()

Temos duas classes: ServicoCarro e ServicoMoto que implementam a interface IServico, cada uma resolvendo seu problema.

Agora vamos criar a classe executora, que receberá a interface:

using System;

namespace BasicDI
{
    public class ExecutaServico
    {
        private IServico _servico;
        public ExecutaServico(IServico servico)
        {
            _servico = servico;
        }

        public void Executa()
        {
            _servico.Executa();
        }
    }
}

Veja que nossa classe recebe a interface e depois chama o método Executa(). Agora temos um desacoplamento, pois podemos passar para a classe qualquer objeto que implemente a interface, mudando o objeto a ser executado, sem modificar o nosso código!

Vejam a execução:

using System;
using System.Data;
using Microsoft.Data.SqlClient;

namespace BasicDI
{
    class Program
    {
        static void Main(string[] args)
        {
            var execCarro = new ExecutaServico(new ServicoCarro());
            execCarro.Executa();
            
            var execMoto = new ExecutaServico(new ServicoMoto());
            execMoto.Executa();

        }
    }

}

Na execução estamos passando duas classes diferentes para o mesmo executor, chamando o mesmo método, pois ambas implementam a mesma interface!

Mecanismos de injeção de dependência

Agora que você entendeu o princípio básico da injeção, deve estar pensando: O ASP.NET Core não faz isto e também no ASP.NET não era bem assim que se fazia! E você está certo! Este é o conceito!

O que se usa são os frameworks de injeção de dependência, que facilitam a vida para você, implementando este controle automaticamente.

Alguns dos frameworks mais conhecidos são:

  • NInject
  • SimpleInjector
  • Windsor

Exemplo com NInject

Como o NInject é um dos mais conhecidos, vamos montar um exemplo com ele. A idéia é basicamente a mesma, teremos uma Interface e uma classe que implementa esta interface.

A grande diferença agora é que não precisamos mais instanciar a classe! Opa como assim!

Isto mesmo, o mecanisco de injeção de dependência, neste caso o NInject, fará isto para nós “magicamente”!

Vamos ao exemplo!

Eu criei um projeto console com .NET Core 3.1, mas você pode usar outra versão do .NET caso prefira!

Primeiro precisamos adicionar o pacote do NInject:

Agora temos a Interface e a Classe:

using System;

namespace ExemploNInject
{
    public interface IServico
    {
        public void Executa();
    }

    public class MeuServico : IServico
    {
        public void Executa()
        {
            System.Console.WriteLine("Servico Executado!");
        }
    }
}

Agora vamos implementar a classe executora:

using System;

namespace ExemploNInject
{
    public class ExecutaDI 
    {
        private IServico _servico;
        public ExecutaDI(IServico servico)
        {
            _servico = servico;
        }
        public void Executa()
        {
            _servico.Executa();
        }
    }
}

Por fim, vamos implementar o NInject:

using System;
using Ninject;

namespace ExemploNInject
{
    class Program
    {
        static void Main(string[] args)
        {
            Ninject.IKernel inject = new StandardKernel();  
            inject.Bind<IServico>().To<MeuServico>();  
            var obj = inject.Get<ExecutaDI>();  
            obj.Executa();   
        }
    }
}

Primeiro criamos o objeto “inject” que contém o mecanismo do NInject.

Depois informamos ao NInject quem será injetado, ou seja, toda vez que a interface IServico for utilizada a classe MeuServico será criada e passada!

No construtor da classe executora nós colocamos a interface:


public ExecutaDI(IServico servico)


Por último criamos a instância da classe executora e chamamos o método:


var obj = inject.Get();
obj.Executa();


Neste caso quem instanciou o objeto foi o NInject quando chamamos o “Get”.

Assim não precisamos nos preocupar com a criação dos objetos!

Então o NInject “injeta” um objeto da classe MeuServico toda vez que encontra uma interface IServico.

Conclusão

O injeção de dependência pode reduzir muito código da sua aplicação, deixando-a mais simples!

No próximo artigo vou mostrar o mecanismo de injeção de dependência do ASP.NET Core, que é simplesmente fantástico!

Os exemplos estão no meu Git: https://github.com/carloscds/CSharpSamples

Veja a segunda parte desta série!

Abraços e até a próxima!