Un mapper de objetos es una herramienta para convertir objetos de un tipo en objetos de otro tipo.
Si has seguido los artículos anteriores sobre DTOs, te habrás encontrado con una tarea repetitiva y aburrida.
Tienes tu entidad Usuario con 20 propiedades, y tu UsuarioDto con las mismas 20 propiedades. Y te toca escribir esto:
var dto = new UsuarioDto
{
Nombre = usuario.Nombre,
Apellido = usuario.Apellido,
Email = usuario.Email,
// ... y así 17 líneas más ...
};Esto es código repetitivo. Es fácil olvidar una propiedad y, cuando hay muchos mapeos, termina ensuciando los servicios.
Los mappers de objetos automatizan parte de ese trabajo mediante convenciones, expresiones compiladas o generación de código.
Vamos a comparar dos alternativas habituales: AutoMapper y Mapster.
AutoMapper
AutoMapper es una biblioteca veterana y muy extendida en el ecosistema .NET.
Cómo funciona
AutoMapper funciona basándose en Perfiles. Debes decirle explícitamente qué clases se pueden mapear entre sí.
Instalación
dotnet add package AutoMapperConfiguración del perfil
Creamos una clase que herede de Profile. Aquí definimos las reglas.
using AutoMapper;
public class MappingProfile : Profile
{
public MappingProfile()
{
// Mapeo simple: Propiedades con mismo nombre se copian solas
CreateMap<Producto, ProductoDto>();
// Mapeo inverso (de DTO a Entidad)
CreateMap<CrearProductoDto, Producto>();
// Mapeo personalizado: Si los nombres no coinciden
CreateMap<Usuario, UsuarioDto>()
.ForMember(dest => dest.NombreCompleto,
opt => opt.MapFrom(src => $"{src.Nombre} {src.Apellido}"));
}
}Registro e inyección
En Program.cs, registramos el servicio indicando un tipo de la assembly donde están los perfiles.
builder.Services.AddAutoMapper(
cfg => cfg.LicenseKey = "<license-key>",
typeof(MappingProfile));Desde AutoMapper 13, AddAutoMapper forma parte del paquete principal AutoMapper. El paquete antiguo AutoMapper.Extensions.Microsoft.DependencyInjection quedó discontinuado. AutoMapper 15 requiere revisar su licencia y configurar una clave; también puede descubrirla mediante la variable AUTOMAPPER_LICENSE_KEY.
Uso
Inyectamos IMapper en nuestro servicio o controlador.
public class ProductoService
{
private readonly IMapper _mapper;
public ProductoService(IMapper mapper)
{
_mapper = mapper;
}
public ProductoDto Get(int id)
{
var entidad = _repo.Get(id);
// Convierte entidad a DTO
return _mapper.Map<ProductoDto>(entidad);
}
}Mapster
En los últimos años, Mapster ha ganado popularidad como alternativa con una API sencilla y opciones de generación de código.
Mapster puede adaptar objetos en tiempo de ejecución y también ofrece generación de código en compilación. Si el rendimiento importa, conviene medir el caso real en lugar de elegir solo por un benchmark genérico.
Cómo funciona
Mapster apuesta por la convención sobre la configuración. A menudo no necesitas configurar nada.
Instalación
dotnet add package MapsterUso directo
No necesitas inyectar nada si no quieres. Mapster añade métodos de extensión a todos tus objetos.
using Mapster;
public ProductoDto Get(int id)
{
var entidad = _repo.Get(id);
// Método de extensión .Adapt<T>()
var dto = entidad.Adapt<ProductoDto>();
return dto;
}Configuración global
Si necesitas mapeos personalizados, puedes configurarlos al inicio de la app:
TypeAdapterConfig<Usuario, UsuarioDto>
.NewConfig()
.Map(dest => dest.NombreCompleto, src => src.Nombre + " " + src.Apellido);AutoMapper y Mapster
| Característica | AutoMapper | Mapster |
|---|---|---|
| Configuración habitual | Perfiles y IMapper | Convenciones, configuración global o código generado |
| Uso | Inyección de IMapper | Métodos de extensión como Adapt o servicios configurados |
| Proyección de consultas | ProjectTo | ProjectToType |
| Licencia | Requiere revisar la licencia desde la versión 15 | MIT |
Mapeo manual
También podemos no usar ninguna librería y escribir métodos de mapeo explícitos.
Escribir tus propios métodos de extensión .ToDto() es repetitivo, pero tiene ventajas claras:
- Rendimiento predecible: Una asignación directa evita el coste del mapeador.
- Referencias: Puedes hacer “Click derecho -> Buscar referencias” en una propiedad y saber exactamente dónde se está usando. Con AutoMapper, esa relación queda oculta al IDE.
- Depuración: Si falla el mapeo, pones un breakpoint y lo ves.
// Mapeo manual con métodos de extensión
public static class ProductoMappers
{
public static ProductoDto ToDto(this Producto entidad)
{
return new ProductoDto(entidad.Id, entidad.Nombre, entidad.Precio);
}
}
// Uso
return entidad.ToDto();