AdvancedRepository.Integrations.Mapperly 1.1.0

dotnet add package AdvancedRepository.Integrations.Mapperly --version 1.1.0
                    
NuGet\Install-Package AdvancedRepository.Integrations.Mapperly -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AdvancedRepository.Integrations.Mapperly" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="AdvancedRepository.Integrations.Mapperly" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="AdvancedRepository.Integrations.Mapperly" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add AdvancedRepository.Integrations.Mapperly --version 1.1.0
                    
#r "nuget: AdvancedRepository.Integrations.Mapperly, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package AdvancedRepository.Integrations.Mapperly@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=AdvancedRepository.Integrations.Mapperly&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=AdvancedRepository.Integrations.Mapperly&version=1.1.0
                    
Install as a Cake Tool

Repo.Integrations.Mapperly

Integración opcional con Mapperly para AdvancedRepository.NET8. Esta integración permite mapear entidades a DTOs en tiempo de compilación sin agregar dependencias al paquete core.

¿Por qué Mapperly?

  • Zero runtime overhead: El mapeo se genera en tiempo de compilación
  • Sin reflection: Rendimiento máximo en escenarios de alta carga
  • AOT-friendly: Compatible con Native AOT y trimming
  • Descubrimiento en tiempo de diseño: Errores de mapeo se detectan al compilar

Instalación

dotnet add package AdvancedRepository.Integrations.Mapperly

Uso Básico

1. Define tus DTOs

public class UserDto
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string Role { get; set; } = string.Empty;
    public DateTime CreatedAt { get; set; }
}

public class CreateUserRequest
{
    public string Name { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string Role { get; set; } = string.Empty;
}

2. Crea tu Mapper con Mapperly

using Riok.Mapperly.Abstractions;
using YourNamespace.Entities;
using YourNamespace.DTOs;

[Mapper]
public partial class UserMapper
{
    public partial UserDto ToDto(User entity);
    public partial User ToEntity(CreateUserRequest request);
    public partial IEnumerable<UserDto> ToDtoCollection(IEnumerable<User> entities);
    
    // Mapperly genera automáticamente el código de mapeo
}

3. Úsalo en tu API/Controlador

public class UsersController : ControllerBase
{
    private readonly IRepo<User> _userRepo;
    private readonly UserMapper _mapper = new();

    public UsersController(IRepo<User> userRepo)
    {
        _userRepo = userRepo;
    }

    [HttpGet]
    public async Task<ActionResult<IEnumerable<UserDto>>> GetAll()
    {
        var users = await _userRepo.GetAllAsync();
        return Ok(_mapper.ToDtoCollection(users));
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<UserDto>> GetById(int id)
    {
        var user = await _userRepo.GetById(id);
        if (user == null) return NotFound();
        return Ok(_mapper.ToDto(user));
    }

    [HttpPost]
    public async Task<ActionResult<UserDto>> Create(CreateUserRequest request)
    {
        var entity = _mapper.ToEntity(request);
        entity.CreatedAt = DateTime.UtcNow;
        
        var created = await _userRepo.Insert(entity);
        return CreatedAtAction(nameof(GetById), new { id = created.Id }, _mapper.ToDto(created));
    }
}

Configuración Avanzada

Mapeo con transformaciones

[Mapper]
public partial class OrderMapper
{
    [MapProperty(nameof(Order.TotalAmount), nameof(OrderDto.FormattedTotal))]
    public partial OrderDto ToDto(Order order);

    // Método de conversión personalizado
    private string FormatCurrency(decimal amount) => $"${amount:N2}";
}

Ignorar propiedades

[Mapper]
public partial class ProductMapper
{
    [MapperIgnoreTarget(nameof(ProductDto.InternalCode))]
    public partial ProductDto ToDto(Product entity);
}

Mapeo bidireccional

[Mapper]
public partial class CategoryMapper
{
    public partial CategoryDto ToDto(Category entity);
    public partial Category ToEntity(CategoryDto dto);
}

Patrones Recomendados

1. Mapper como Singleton

Los mappers de Mapperly son stateless y thread-safe:

// En Program.cs
builder.Services.AddSingleton<UserMapper>();
builder.Services.AddSingleton<ProductMapper>();

2. Extensión del Repositorio (opcional)

Si necesitas mapeo directo en el repositorio, extiende RepoBase:

public class UserRepository : RepoBase<User, YourDbContext>
{
    private readonly UserMapper _mapper;

    public UserRepository(
        YourDbContext context, 
        ILogger logger, 
        UserMapper mapper) : base(context, logger)
    {
        _mapper = mapper;
    }

    public async Task<IEnumerable<UserDto>> GetAllAsDtoAsync()
    {
        var entities = await GetAllAsync();
        return _mapper.ToDtoCollection(entities);
    }
}

3. Capa de Servicios con Mapeo

public class UserService
{
    private readonly IRepo<User> _userRepo;
    private readonly UserMapper _mapper;

    public UserService(IRepo<User> userRepo, UserMapper mapper)
    {
        _userRepo = userRepo;
        _mapper = mapper;
    }

    public async Task<UserDto?> GetUserAsync(int id)
    {
        var user = await _userRepo.GetById(id);
        return user != null ? _mapper.ToDto(user) : null;
    }

    public async Task<IEnumerable<UserDto>> GetActiveUsersAsync()
    {
        var spec = new ActiveUsersSpecification();
        var users = await _userRepo.GetAllBySpecAsync(spec);
        return _mapper.ToDtoCollection(users);
    }
}

Arquitectura: ¿Dónde va el mapeo?

┌─────────────────────────────────────────────────────────────┐
│  Controller/API Layer                                       │
│  - Recibe DTOs/Requests                                     │
│  - Devuelve DTOs/Responses                                  │
│  - Usa Mapperly para convertir a/desde entidades            │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│  Service Layer (opcional)                                   │
│  - Lógica de negocio                                        │
│  - Orquesta operaciones                                     │
│  - Puede usar mappers si transforma datos                   │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│  Repository Layer (Core)                                    │
│  - Trabaja SOLO con Entidades                               │
│  - NO sabe nada de DTOs ni mappers                          │
│  - IRepo<T> solo acepta y devuelve T (entidad)              │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│  Database                                                   │
│  - Persiste entidades                                       │
└─────────────────────────────────────────────────────────────┘

Regla de oro: El repositorio nunca devuelve DTOs. El mapeo ocurre en la capa de aplicación/controladores.

Comparación: Mapperly vs AutoMapper

Característica Mapperly AutoMapper
Tiempo de generación Compilación Runtime
Reflection No Sí
Performance Máxima Buena
Configuración Atributos/Convenio Fluent API
Debugging Código generado visible Perfil interno
AOT Support ✅ Completo ⚠️ Limitado

Requisitos

  • .NET 8.0 o .NET 9.0
  • Riok.Mapperly 4.1.0+
  • AdvancedRepository.NET8 1.0.0+

Licencia

MIT - Ver LICENSE para más detalles.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 148 4/8/2026
1.0.4 133 4/8/2026
1.0.3 121 4/7/2026