Skip to main content
SEMastery
Fundamentalsbeginner

The Best Way to Map Objects in .NET in 2024 (and Beyond)

Learn the best way to map objects in .NET: manual mapping, Mapperly source generators, and why teams are moving away from AutoMapper after it went commercial.

11 min readUpdated December 16, 2025

Think about ordering food at a restaurant. The kitchen has a big recipe card with everything: the supplier name, the cost of each item, the chef's secret notes. But the menu you get at your table is much smaller. It only shows the dish name, a short description, and the price. Someone takes the full kitchen card and copies just the right parts onto the customer menu.

That copying job is exactly what object mapping is in .NET. You have one object full of details (like a database row), and you need to copy some of its data into another object that has a different shape (like the response your API sends back). You map the fields from one to the other.

In this guide you will learn the different ways to do this in .NET, which one is best for your project, and why so many teams changed their plan in 2024 and 2025.

Why do we even need mapping?

In a real app you usually have more than one kind of object for the "same" thing.

  • An entity is the object that matches your database table. It may have secret fields like a password hash or an internal note.
  • A DTO (Data Transfer Object) is the object you send out of your API or take in. It only has the fields the outside world is allowed to see.

You never want to send your database entity straight out. It might leak private data, and it ties your API shape to your database shape. So you copy the safe fields into a DTO. That copy step is mapping.

Mapping sits between your database entity and the response you send to users.

Here is a tiny example. We have an Order entity and an OrderResponse DTO.

// The full entity that lives in the database.
public class Order
{
    public Guid Id { get; set; }
    public string CustomerName { get; set; } = "";
    public decimal Total { get; set; }
    public string InternalNote { get; set; } = "";   // secret, do not send out
    public DateTime CreatedAt { get; set; }
}
 
// The smaller object we send back from the API.
public record OrderResponse(
    Guid Id,
    string CustomerName,
    decimal Total,
    DateTime CreatedAt);

Notice that InternalNote is not in OrderResponse. That is the whole point. Mapping lets us pick only the safe fields.

The three main ways to map in .NET

There are three common approaches. Let us meet them one by one.

  1. Manual mapping — you write the copy code yourself.
  2. Source-generated mapping — a tool writes the copy code for you at build time. Mapperly and Mapster (with its tool) live here.
  3. Reflection-based mapping — a library copies fields at run time by inspecting types. AutoMapper is the famous one here.

Choosing a mapping approach

Start
Small?
Manual
Many DTOs?
Mapperly
Reflection

Steps

1

Start

You need to map objects

2

Small?

Few, simple objects

3

Manual

Just write plain C#

4

Many DTOs?

Lots of large objects

5

Mapperly

Generate code at build

6

Reflection

Older default, now paid for big teams

A simple path from project size to mapping choice.

Let us look at each one closely.

Approach 1: Manual mapping

Manual mapping means you simply write the copy code by hand. No library at all.

public static class OrderMapping
{
    // Plain C#. Easy to read. Easy to debug.
    public static OrderResponse ToResponse(this Order order)
    {
        return new OrderResponse(
            order.Id,
            order.CustomerName,
            order.Total,
            order.CreatedAt);
    }
}

Then in your code you write order.ToResponse(). That is it.

People sometimes think manual mapping is "old fashioned" or "not clever enough". That is not true. Manual mapping has real strengths:

  • It is the fastest option. There is no extra magic at run time.
  • It is compile-time safe. If you rename a field, the build breaks and tells you right away.
  • It is easy to debug. You can put a breakpoint on any line.
  • It needs no library, so nothing to update and nothing to pay for.

The only real downside shows up when you have many big objects. Writing the same kind of copy code 50 times gets boring and you can make small mistakes. That is where the next approach helps.

Approach 2: Source-generated mapping (Mapperly)

A source generator is a tool that runs while your project builds. It looks at your code and writes extra C# code for you. The generated code becomes part of your program, just like code you typed yourself.

Mapperly is the most popular mapping source generator. You describe the mapping with a small class, and Mapperly writes the actual copy method during the build.

using Riok.Mapperly.Abstractions;
 
[Mapper]
public partial class OrderMapper
{
    // Mapperly fills in the body of this method at build time.
    public partial OrderResponse ToResponse(Order order);
}

The word partial is the key. You leave the method empty. Mapperly generates the full body in another file. The generated code is plain, readable C# that does direct property assignment, like the manual version above. You can even open it and read it.

Because the code is generated at build time, Mapperly gives you the best of both worlds:

  • It is fast, almost as fast as hand-written code, because there is no reflection at run time.
  • It is compile-time safe. If a field does not match, you get a warning or error during the build.
  • It is free under the Apache 2.0 licence.
  • It saves you from writing repetitive copy code.
How a source generator like Mapperly fits into the build.

Mapster is another tool in this family. It can also generate code at compile time using Mapster.Tool, and it is known for being fast and flexible. Mapperly and Mapster are both good picks; this guide leans on Mapperly because its generated code is very easy to read.

Approach 3: Reflection-based mapping (AutoMapper)

For many years, AutoMapper was the default choice in .NET. It uses reflection, which means it inspects your objects at run time and copies matching fields. You set up "profiles" that tell it how the two types line up.

This was convenient. You did not write copy code, and AutoMapper figured out most fields by name. But reflection has costs:

  • It is slower because the work happens at run time, every time you map.
  • It uses more memory.
  • It is not compile-time safe. If a field is missing, you often find out only when the app runs and a test fails or a value comes back empty.
  • The mapping code is hidden, so it is harder to step through and debug.

In one common benchmark mapping 100,000 objects, Mapperly finished in about 28.6 ms while AutoMapper took about 36.4 ms. That is roughly 22% faster, with less memory used. Numbers vary by machine and version, but the pattern is steady: generated code beats reflection.

The big 2024 and 2025 change: AutoMapper went commercial

Here is the news that made many teams rethink their choice.

Through 2024, AutoMapper was free and open source. Then, in July 2025, Jimmy Bogard, the creator, launched commercial editions of AutoMapper and MediatR under a company called Lucky Penny Software. MassTransit, another well-known library, also moved toward a commercial model around the same time.

The important details:

  • AutoMapper and MediatR are still free for individuals and for companies with less than 5 million USD in yearly revenue.
  • Larger teams now need a paid licence. Pricing is by team size, for example a Standard tier for small teams and higher tiers for bigger ones.
  • If you already use it, your existing version keeps working. You do not have to change anything overnight.

So why did this push teams to alternatives? Because a free, open library felt safe to depend on forever. Once money and revenue limits enter the picture, teams worry about future costs and rules. Many decided it was simpler to move to a free, source-generated mapper like Mapperly, which is fast, modern, and Apache 2.0 licensed.

Why teams moved off AutoMapper

Free for years
Went commercial 2025
Revenue limits
Look at options
Pick Mapperly

Steps

1

Free for years

AutoMapper was the default

2

Went commercial 2025

Paid for larger teams

3

Revenue limits

5M USD rule applies

4

Look at options

Compare free, fast mappers

5

Pick Mapperly

Source-generated and free

The thinking that led many .NET teams toward Mapperly.

Side-by-side comparison

Here is a simple table to compare the three approaches.

ApproachSpeedCompile-time safeCostBest for
Manual mappingFastestYesFreeSmall projects, few objects
Mapperly / MapsterVery fastYesFreeMany objects, large apps
AutoMapper (reflection)SlowerNoFree under 5M USD, else paidExisting projects already using it

And here is how the workflow differs for each.

StepManualMapperlyAutoMapper
Where mapping runsYou write itBuild timeRun time
Add a library?NoYes (free)Yes (paid for big teams)
See the copy code?YesYes, generatedNo, hidden
Error shows upAt buildAt buildAt run time

A complete Mapperly example

Let us put Mapperly to work with a slightly bigger example. Say we also want a list of order items in the response.

using Riok.Mapperly.Abstractions;
 
public class OrderItem
{
    public string ProductName { get; set; } = "";
    public int Quantity { get; set; }
}
 
public record OrderItemResponse(string ProductName, int Quantity);
 
[Mapper]
public partial class OrderMapper
{
    // Map a single order. Mapperly handles the nested list too.
    public partial OrderResponse ToResponse(Order order);
 
    // Mapperly also generates this helper for the list items.
    public partial OrderItemResponse ToItemResponse(OrderItem item);
}

Mapperly notices the nested list and wires it up for you. The generated code is just direct assignments and a simple loop, so it stays fast and readable.

So, what is the best way?

There is no single winner for every project. But here is honest, simple advice for 2024 and beyond:

  • Small project, few objects? Use manual mapping. It is the simplest and fastest, and you avoid any library.
  • Bigger project with many DTOs? Use Mapperly (or Mapster). You get compile-time safety and great speed without writing the same copy code again and again.
  • Already on AutoMapper and under the revenue limit? You can stay for now. But for new projects, prefer a source generator so you are not tied to a paid model later.

The clear trend is away from run-time reflection and toward code that is generated or written by hand. That code is faster, safer, and easier to read.

A quick decision flow for picking your mapper.

References and further reading

Quick recap

  • Mapping copies data from one object (like a database entity) into another object of a different shape (like a DTO). It is like copying the right parts of a kitchen recipe card onto a customer menu.
  • There are three main ways: manual mapping, source-generated mapping (Mapperly, Mapster), and reflection-based mapping (AutoMapper).
  • Manual mapping is fast, safe, free, and great for small projects.
  • Mapperly writes mapping code at build time. It is fast, free (Apache 2.0), and compile-time safe. It is the strong pick for larger apps.
  • AutoMapper uses reflection, which is slower and not compile-time safe. In July 2025 it went commercial, free only for teams under 5 million USD in revenue.
  • For new projects, prefer manual mapping or a source generator like Mapperly. The .NET world is moving away from run-time reflection.

Related Posts