.NET MAUI - Injeção de dependência


 Hoje veremos a injeção de dependência no .NET MAUI.

O .NET MAUI é de código aberto e é a evolução do Xamarin.Forms, estendido de cenários móveis a desktops, com controles de IU reconstruídos do zero para desempenho e extensibilidade.

Se você já usou o Xamarin.Forms anteriormente para criar aplicações multiplataforma, você notará muitas semelhanças com o .NET MAUI.

recursos:

Injeção de dependência

A injeção de dependência é apenas uma maneira de um objeto (cliente) receber outros objetos (serviços) dos quais depende. Aqui, injeção significa o método ou código que passa o objeto de serviço para o objeto cliente. A injeção de dependência é uma forma de aplicar a inversão de controle, onde a classe de serviço injetará dependências em um objeto em tempo de execução.

Para realizar a injeção de dependência no .NET MAUI podemos usar os recursos do container DI nativo da plataforma .NET da mesma forma que fazemos em aplicações ASP .NET Core sem precisar usar plugins de terceiros.

Para mostrar isso vamos criar um novo projeto no VS 2022 Preview usando o template .NET MAUI App com o nome MauiApp_DI.

Teremos assim o projeto padrão .NET  MAUI criado que apresenta o seguinte resultado:

Nota: O .NET MAUI usa o modelo do Generic Host, e assim podemos inicializar nossos aplicativos a partir de um único local. Ele também nos oferece a capacidade de configurar fontes, serviços e bibliotecas de terceiros a partir de um local centralizado. Fazemos isso criando uma classe MauiProgram com um método CreateMauiApp. Cada plataforma invoca esse método automaticamente quando seu aplicativo for inicializado.

Vamos abrir o arquivo MauiProgram deste projeto :

namespace MauiApp_DI;

public static class MauiProgram
{
   public static MauiApp CreateMauiApp()
   {
        var builder = MauiApp.CreateBuilder();
               builder
 
.UseMauiApp<App>()
  .ConfigureFonts(fonts =>
    {
      fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
      fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
   });
return builder.Build();
     }
}

Neste código temos a classe estática CreateMauiApp onde usamos o método de extensão UseMauiApp<App> para invocar a classe App e assim inicializar a aplicação .NET MAUI.

A classe App é uma partial Class que no construtor cria uma instância de AppShell() renderizando o código XAML e apresentando a MainPage:

public partial class App : Application
{
    public App()
    {
       InitializeComponent();
       MainPage =
new AppShell();
     }
}

Então é assim que esta implementada o código para iniciar a aplicação.

Aplicando a injeção de dependência

Vamos agora aplicar a injeção de dependência alterando o código da classe MauiProgram:

namespace MauiApp_DI;

public static class MauiProgram
{
   public static MauiApp CreateMauiApp()
   {
        var builder = MauiApp.CreateBuilder();
               builder
  .UseMauiApp<App>()
  .ConfigureFonts(fonts =>
    {
      fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
      fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
   });

       builder.Services.AddSingleton<AppShell>();
        return builder.Build();
     }
}

Incluímos a seguinte linha de código:

 builder.Services.AddSingleton<AppShell>();

Onde estamos usando os recursos de IServiceCollection disponível a partir do namespace Microsoft.Extensions.DependencyInjection onde estamos incluindo um serviço do tipo singleton especificado em AppShell.

Com isso registramos o serviço no container DI nativo e podemos obter uma instância desse serviço para fazer a inversão de controle usando a injeção de dependência.

Com isso podemos retornar ao código da classe App:

public partial class App : Application
{
    public App()
    {
       InitializeComponent();
       MainPage = new AppShell();
     }
}

E agora podemos  substituir a criação da instância de AppShell obtendo uma instância do serviço que foi registrado no container DI. Podemos fazer isso usando o construtor da classe:

public partial class App : Application
{
    public App(
AppShell shellPage)
    {
       InitializeComponent();
     
  MainPage = shellPage;
     }
}

Executando o projeto vamos obter o mesmo resultado, agora usando a injeção de dependência.

Vejamos agora outro exemplo de aplicação da injeção de dependência.

Vamos criar no projeto a classe MainPageViewModel com a propriedade Mensagem:

public class MainPageViewModel
{
    public string Mensagem { get; set; } = ".NET MAUI Injeção de dependência !!!";
}

A seguir vamos registrar esta classe no container DI nativo para obter a sua instância via injeção de dependência:

namespace MauiApp_DI;

public static class MauiProgram
{
   public static MauiApp CreateMauiApp()
   {
        var builder = MauiApp.CreateBuilder();
               builder
  .UseMauiApp<App>()
  .ConfigureFonts(fonts =>
    {
      fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
      fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
   });

       builder.Services.AddSingleton<AppShell>();
       builder.Services.AddSingleton<MainPageViewModel>();
       return builder.Build();

     }
}

Agora vamos realizar a injeção de dependência usando a classe MainPageViewModel e injetando-a no construtor da classe AppShell:

public partial class AppShell : Shell
{
   public AppShell(
MainPageViewModel viewModel)
   {
        InitializeComponent();
      
 BindingContext = viewModel;
    }
}

A seguir vamos usar a instância da view model e atribuí-la ao BindingContext.

Agora podemos alterar o código do arquivo MainPage.xaml vinculando a propriedade Mensagem da view model com uma Label:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp_DI.MainPage">

    <ScrollView>
        <VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Center">

            <Image
                Source="dotnet_bot.png"
                SemanticProperties.Description="Cute dot net bot waving hi to you!"
                HeightRequest="200"
                HorizontalOptions="Center" />               

            <Label
                Text=
"{Binding Mensagem}"
                SemanticProperties.HeadingLevel="Level1"
                FontSize="32"
                HorizontalOptions="Center" />

            ...
            ...
}

Executando o projeto teremos a exibição do texto da mensagem definida na propriedade Mensagem da view model MainPageViewModel que esta sendo injetada no construtor da classe AppShell:

Desta forma agora podemos usar a injeção de dependência nativa em aplicações .NET MAUI de forma bem simples e isso vai tornar nossas aplicações mais robustas.

"E eu, quando o vi, caí a seus pés como morto; e ele pôs sobre mim a sua destra, dizendo-me: Não temas; Eu sou o primeiro e o último; E o que vivo e fui morto, mas eis aqui estou vivo para todo o sempre. Amém. E tenho as chaves da morte e do inferno."
Apocalipse 1:17,18

Referências:


José Carlos Macoratti