C# - Injeção de dependência(DI) e Inversão de Controle(IoC) - II


 Neste artigo rever os conceitos de injeção de depêndência e de inversão de controle no .NET Core usando a linguagem C#.

Continuando a primeira parte do artigo veremos como usar o contêiner de injeção de dependência nativa da .NET Core.

Usando o contêiner DI da .NET Core

Usando o contêiner de injeção de dependência nativa da .NET Core podemos definir o mapeamento das interfaces para as suas classes concretas e podemos também especificar se o serviço deve ser usado como um singleton, ou uma nova instância deve ser criada toda vez que for usada.

A seguir vamos usar o contêiner de injeção de dependência nativa em nossa aplicação onde definimos a classe RecepcaoService que implementa a interface IRecepcaoService e também a classe Controller. Vamos criar outro projeto chamado NetCore_DI_Nativo e aproveitar o código criado para essas classes e para a interface.

Para poder usar os recursos do contêiner de injeção de dependência nativa temos que incluir no projeto as seguintes referências:

Dentro da classe Program, vamos criar o método RegistrarServices com o código a seguir:

        using Microsoft.Extensions.DependencyInjection;
        static ServiceProvider RegistrarServices()
        {
            var services = new ServiceCollection();
            services.AddSingleton<IRecepcaoService, RecepcaoService>();
            services.AddTransient<Controller>();
            return services.BuildServiceProvider();
        }

Vamos entender o código:

A classe ServiceProvider fornece um provedor de serviços unificado para VSPackages gerenciados. Ela implementa a interface IServiceProvider e usa uma instância de IServiceProvider como um argumento de construtor.

Criamos uma instância do objeto ServiceCollection que é definido no namespace : Microsoft.Extensions.DependencyInjection  e é uma implementação de IServiceCollection

A seguir usamos os métodos AddSingleton e AddTransient, métodos de extensão são usados para registrar os tipos que desejamos mapear.

Há quatro modos de vida para um serviço que está sendo injetado:

  1. Singleton : Um objeto do serviço é criado e fornecido para todas as requisições. Assim, todas as requisições obtém o mesmo objeto;
  2. Escope : Um objeto do serviço é criado para cada requisição. Dessa forma, cada requisição obtém uma nova instância do serviço;
  3. Transient : Um objeto do serviço é criado toda a vez que um objeto for requisitado;
  4. Instance : Você é responsável por criar um objeto do serviço. O framework de DI então usa esse instância em um modo Singleton;

No exemplo estamos registrando o mapeamento da interface IRecepcaoService para RecepcaoService a sua implementação concreta, de forma que quando fizermos a injeção vamos obter uma instância da classe concreta.

Também registramos a classe Controller que assim poderá ter a sua instãncia recuperada do contêiner.

Dessa forma a classe RecepcaoService será instanciada quando a interface for solicitada e a classe Controller será instanciada quando for solicitado.

A configuração do contêiner DI também define o tempo de vida dos serviços. Com RecepcaoService, a mesma instância sempre é retornada quando IRecepcaoService for solicitado. Para Controller uma nova instãncia será criada a cada requisição.

Vamos agora definir o código do método Main para invocar o método RegistrarServices para fazer o registro no contêiner DI e então vamos invocar o método GetRequiredService do ServiceProvider para obter uma referência a instância de Controller:

          static void Main(string[] args)
        {
            using (ServiceProvider container = RegistrarServices())
            {
                var controller = container.GetRequiredService<Controller>();
                string resultado = controller.Ola("Macoratti");
                Console.WriteLine(resultado);
            }
        }

Quando você inicia o aplicativo, na invocação do método GetRequiredService, o contêiner DI cria uma instância da classe Controller.

O construtor de Controller requer um objeto implementando IRecepcaoService, e, essa interface também é registrada no contêiner; assim para IRecepcaoService um objeto RecepcaoService precisa ser retornado.

A classe RecepcaoService tem um construtor padrão, para que o contêiner possa criar uma instância e passar essa instância para o construtor Controller.

O que acontece se nem toda dependência estiver registrada no contêiner DI ?

Para ver isso em ação, você pode comentar/remover a configuração de IRecepcaoService do contêiner DI.

Nesse caso, o contêiner lança uma exceção do tipo InvalidOperationException conforme a figura abaixo:

Vimos assim como usar o contêiner de injeção de dependência nativa do .NET COre em nossa aplicação console. Ele também é muito usado em aplicações ASP .NET Core.

Pegue o código projeto aqui:  NetCore_DI2.zip

"Disse-lhe, pois, Pilatos: Logo tu és rei? Jesus respondeu: Tu dizes que eu sou rei. Eu para isso nasci, e para isso vim ao mundo, a fim de dar testemunho da verdade. Todo aquele que é da verdade ouve a minha voz."
João 18:37

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 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?

Referências:


José Carlos Macoratti