AutoMapper e ASP.NET Core: mapeamento entre objetos – Parte #1

Nesta série de dois artigos, falarei sobre a biblioteca AutoMapper.

Neste primeiro, vão ser apresentados seus benefícios, e como adicioná-la em seu projeto. Finalmente, um exemplo será mostrado.

Já na segunda parte, serão mostrados exemplos de mapeamento mais complexos.

Código-fonte pode ser encontrado aqui.


Quer ser notificado sobre os próximos artigos, lives semanais, eventos e treinamentos? Entre no canal LuisDev no Telegram!


Mapeamento entre objetos

Antes de apresentar o AutoMapper, é essencial entender o problema a ser resolvido por ele.

Imagine a seguinte situação: você tem uma classe Pessoa, que tem diversas propriedades. Informações como documentos, data de nascimento, estado civil, entre outros, são armazenado nelas.

Como você é um bom programador, preocupado em manter a separação entre modelos de representação, você cria um modelo de entrada (ou Input Model), e uma entidade do domínio. A imagem abaixo representa ambas.

Classe PersonInputModel
Classe Person

Com isso, toda vez que a classe Pessoa for alterada, você não arriscará afetar o cadastro dela, por exemplo. O modelo de entrada está centrado em PersonInputModel, enquanto o de domínio está em Person.

Considere que é necessário instanciar Person com os dados informados no modelo de entrada. Isso poderia ser feito utilizando um construtor vazio, e propriedades com setters públicos, ou com um construtor com os parâmetros necessários.

De uma maneira ou de outra, vai ficar abarrotado de parâmetros sendo passados. A classe Person tem muitas propriedades, e dentre elas várias estão também em PersonInputModel. Além disso, existe a chance de em outros lugares do seu código requerer instanciar esse objeto. O caminho inverso também é feito, no caso, de uma entidade do domínio para um modelo de saída (ou View Model).

Construtores com muitos parâmetros, setters públicos, e mais

Vou ser bem sincero. Já vi diversos desenvolvedores preferirem utilizar setters públicos e construtores sem parâmetros, devido à quantidade absurda de parâmetros. É algo que parece deixar tudo mais prático, porém o risco de se esquecer de aplicar uma alteração em diversas partes do sistema, ao usar esses construtores, é altíssimo (já vi inúmeras vezes isso). Construtores ajudariam a detectar essas alterações que quebram, mas um construtor com muitos parâmetros tampouco é muito prático.

Olha o exemplo abaixo de um mapeamento manual, explicado nas frases passadas.

Mapeamento através de construtor.

E é para resolver este tipo de problema que o AutoMapper se propõe.

Introdução ao AutoMapper

O AutoMapper é uma biblioteca que ajuda a remover esse trabalho tedioso de mapear um objeto a outro. Ao invés de dependermos de construtores com muitos parâmetros, ou perder o feedback de regressão ao usar construtores sem parâmetro, utilizamos ela para fazer o trabalho de uma maneira bem mais confiável.

Instalando

Primeiramente, instalamos a biblioteca AutoMapper.Extensions.Microsoft.DependencyInjection, que vai nos fornecer o método de extensão para obter as classes que vão definir os mapeamentos. Como ela tem dependência no pacote “raiz” AutoMapper, ambos serão instalados juntos.

Instalando o pacote AutoMapper usando o .NET CLI

Utilizando o AutoMapper

Para começar a mapear entre objetos em sua aplicação, é necessário criar classes que descrevam como vai ser feito isso. Por mais que as classes entre si contenham a mesma nomenclatura de propriedades, isso é necessário.

Essas classes devem herdar da classe Profile, do namespace AutoMapper. Em seu construtor, os mapeamentos possíveis serão definidos.

Para este artigo, consideremos duas classes com propriedades de mesmo nome. Elas foram mostradas anteriormente: PersonInputModel, e Person.

Vamos criar uma classe Profile que vai mapear de PersonInputModel para Person, e vice-versa. Essa classe será chamada PersonProfile.

Classe PersonProfile

O que ela diz, basicamente, é: permita o mapeamento da primeira classe definida como parâmetro de tipo, para a segunda. Note que nenhum comportamento além do padrão é especificado.

Em seguida, configuraremos para que nossa aplicação a utilize. Adicionamos, na classe Startup, a chamada ao método IServiceCollection.AddAutoMapper, passando Assembly (ou tipo contido do Assembly) utilizado para obter os perfis de mapeamento.

Adicionando o AutoMapper na aplicação

Após isso, vamos criar um Controller, com um endpoint “api/person“. Ele permitirá uma requisição HTTP POST, contendo o PersonInputModel no corpo. Nele, é feita a conversão, e o objeto da entidade é retornado para o cliente.

Implementando o Controller

Note que também foi criado um endpoint que com método HTTP GET, que retornará uma lista de PersonViewModel. Logo abaixo, é mostrada a implementação dessa classe (com as mesmas propriedades que PersonInputModel e Person).

Classe PersonViewModel

Simples, não?

Testando

Para testar a implementação mostrada, utilizei o Postman. Na imagem abaixo, é realizada uma chamada HTTP POST ao endpoint api/people, com um objeto JSON. Note que as propriedades no objeto de retorno foram mapeadas corretamente.

Chamada HTTP POST ao endpoint api/person, utilizando o Postman

Após isso, testamos o endpoint api/people/1, com uma requisição HTTP GET. O resultado é mostrado logo abaixo.

Chamada HTTP GET ao endpoint api/person/1, utilizando o Postman

Que tal? É o máximo, certo?


Inscreva-se na lista de espera do Método .NET Direto ao Ponto, um treinamento completo sobre C#, APIs com ASP.NET Core e Microsserviços:  Inscreva-se aqui.

São quase 200 vídeo-aulas sobre temas como C#, ASP NET Core 5, EF Core, CQRS, Clean Architecture, Autenticação e autorização com JWT, Testes Unitários, além de mini-cursos em Microsserviços, Performance em .NET, ASP NET Core e Azure, Docker, Carreira Internacional em .NET, e mais.


Realizar o mapeamento entre os objetos pode ser uma tarefa bem propensa a erros. Com a biblioteca AutoMapper, essa tarefa fica mamão com açúcar!

Na parte #2, irei mostrar alguns mapeamentos mais complexos, como o uso de descrição de Enums, mapeando de uma lista para um objeto, entre outros.

Nos vemos no próximo artigo!

Comments are closed.
%d blogueiros gostam disto: