Skip to content

Mapperly

Developer UtilitiesUtilitiesC#

What it is

Mapperly is a source generator that produces object mapping code at compile time, with no reflection and no runtime cost.

Declare a partial class with [Mapper] and partial method signatures. The generator writes the implementations, and unmapped members become build warnings.

Installation

dotnet add package Riok.Mapperly

Getting started

The smallest useful thing you can do with it, and what each part means.

Generated mapping
[Mapper]
public partial class BookMapper
{
    public partial BookDto ToDto(Book book);
    public partial List<BookDto> ToDtos(List<Book> books);

    [MapProperty(nameof(Book.Author.Name), nameof(BookDto.AuthorName))]
    public partial BookDto ToDetailedDto(Book book);
}

// The generator emits plain C#, roughly:
//   public partial BookDto ToDto(Book book) =>
//       new BookDto { Id = book.Id, Title = book.Title };

var dto = mapper.ToDto(book);
The generated code is visible in your IDE and steppable in the debugger — the opposite of a reflection-based mapper, where a mismapping is invisible until it produces a null.

Advanced usage

Where the library earns its place over a simpler alternative.

Strictness and custom conversions
[Mapper(
    RequiredMappingStrategy = RequiredMappingStrategy.Both,
    EnumMappingStrategy = EnumMappingStrategy.ByName)]
public partial class OrderMapper
{
    [MapperIgnoreTarget(nameof(OrderDto.ComputedTotal))]
    public partial OrderDto ToDto(Order order);

    // A private method the generator will use for that type pair.
    private static string MapMoney(Money money) => $"{money.Amount:F2} {money.Currency}";
}
RequiredMappingStrategy.Both makes any unmapped member on either side a build warning, so adding a DTO property that nothing populates fails the build rather than returning null.

Errors and fixes

The failures you are most likely to hit, and what actually resolves them.

RMG020: source member is not mapped to any target member
Intended behaviour under strict mapping. Map it, or silence it with MapperIgnoreSource.
Cannot map property of type X to Y
No conversion exists. Add a private method taking X and returning Y; the generator picks it up automatically.

Best practices

  • Set RequiredMappingStrategy.Both and treat mapping warnings as errors.
  • Read the generated code once — it removes any doubt about what the mapping does.
  • Prefer Mapperly over reflection-based mappers for new projects; it is faster and safer.
  • Keep mappers close to the feature they serve rather than in one global file.

Background

Why it exists, and what it was reacting to.

Mapperly answers AutoMapper's two long-standing criticisms: mappings are invisible at runtime and errors surface late. Being a source generator, the mapping is ordinary readable C# you can step through in a debugger.