Mapo 1.1.1

dotnet add package Mapo --version 1.1.1
                    
NuGet\Install-Package Mapo -Version 1.1.1
                    
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="Mapo" Version="1.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Mapo" Version="1.1.1" />
                    
Directory.Packages.props
<PackageReference Include="Mapo" />
                    
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 Mapo --version 1.1.1
                    
#r "nuget: Mapo, 1.1.1"
                    
#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 Mapo@1.1.1
                    
#: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=Mapo&version=1.1.1
                    
Install as a Cake Addin
#tool nuget:?package=Mapo&version=1.1.1
                    
Install as a Cake Tool

Mapo

CI NuGet License: MIT

High-performance, compile-time object mapping for .NET.

Mapo is a Roslyn source generator that writes your mapping code at build time. You get the fluent API of AutoMapper with the runtime speed of hand-written C# — zero reflection, zero allocation overhead, NativeAOT-ready out of the box.

using Mapo.Attributes;

[Mapper]
public partial class UserMapper
{
    public partial UserDto Map(User user);

    static void Configure(IMapConfig<User, UserDto> config)
    {
        config.Map(d => d.FullName, s => s.FirstName + " " + s.LastName);
        // AddressCity is auto-resolved from Address.City via intelligent flattening
    }
}

That's it. Mapo generates a complete, null-safe, inlineable implementation at compile time.


Why Mapo?

  • Zero overhead. Generated code allocates identically to hand-written code. No reflection. No expression tree compilation. No hidden dictionaries.
  • Compile-time safety. Unmapped properties are caught as warnings (or errors in strict mode) before your code ever runs.
  • Refactoring-safe. Lambda-based configuration means IDE renames propagate automatically — no magic strings.
  • NativeAOT-ready. No System.Reflection.Emit, no dynamic code generation. Works with dotnet publish -r linux-x64 --self-contained /p:PublishAot=true.
  • Familiar API. If you've used AutoMapper, you already know Map(), Ignore(), and AddConverter().

Benchmarks

Measured with BenchmarkDotNet on .NET 10 mapping 10,000 complex orders with nested objects, collections, computed fields, and enum conversions:

Method Mean Ratio Allocated Alloc Ratio
Mapo 1,310 us 0.99 3,898.74 KB 1.00
Mapperly 1,323 us 0.99 3,898.74 KB 1.00
Manual 1,332 us 1.00 3,898.74 KB 1.00
Mapster 3,551 us 2.67 4,914.43 KB 1.26
AutoMapper 5,270 us 3.96 6,420.91 KB 1.65

Mapo generates code that is indistinguishable from hand-written C# — identical allocations and identical speed. See Benchmark Details.


Installation

dotnet add package Mapo

Requirements: .NET 6+ (or any runtime supporting netstandard2.0) with Roslyn 4.8+ (ships with .NET SDK 8+).

The NuGet package includes both the public API (Mapo.Attributes) and the source generator (Mapo.Generator). No extra configuration needed.


Quick Start

Step 1: Define your types

public class Product
{
    public string SKU { get; set; } = "";
    public string Name { get; set; } = "";
    public decimal Price { get; set; }
    public Category? Category { get; set; }
}

public record ProductDto(string SKU, string Name, string PriceDisplay, string CategoryName);

Step 2: Create a mapper

using Mapo.Attributes;

[Mapper(StrictMode = true)]
public partial class ProductMapper
{
    public partial ProductDto Map(Product product);

    static void Configure(IMapConfig<Product, ProductDto> config)
    {
        config.Map(d => d.PriceDisplay, s => s.Price.ToString("C"))
              .Map(d => d.CategoryName, s => s.Category.Name);
    }
}

Step 3: Use it

var mapper = new ProductMapper();
var dto = mapper.Map(product);

The generated code handles null-safety (Category?.Name ?? default), selects the best constructor, and uses [MethodImpl(AggressiveInlining)] for optimal JIT behavior.


Features

Feature Description
Basic Mapping Auto-match properties by name (case-insensitive), classes and records
Flattening Address.City auto-maps to AddressCity — recursive up to 4 levels
Property Renaming [MapFrom("SourceName")] attribute for simple renames without Configure
Custom Mappings Strongly-typed lambda expressions via IMapConfig<S,T>
Collections List<T>, T[], IEnumerable<T> with devirtualized for loops
Enum Mapping Enum-to-enum switch, enum-to-string .ToString(), string-to-enum Enum.Parse
Nullable Handling string?string (null-forgiving), MyClass? (null-conditional), List<T>? (empty list), int?int (?? default)
Records & Constructors Full support for immutable types, primary constructors, init-only, required
Update Mapping Mutate existing objects with void mapping methods
Dependency Injection Constructor-inject services, use them in Configure lambdas
Polymorphic Dispatch [MapDerived] for inheritance hierarchies
Circular References UseReferenceTracking prevents stack overflow in object graphs
Global Converters AddConverter<TIn, TOut>() applies to all matching properties
Reverse Mapping .ReverseMap() generates bidirectional mappers
Async Streaming Auto-generated IAsyncEnumerable<T> extensions for EF Core
Strict Mode Compile-time errors for unmapped properties
IDE Quick Fixes Ctrl+. to auto-fix unmapped properties and non-partial classes

Documentation

Document Description
Usage Guide Complete reference with examples for every feature
Architecture Internal design: parse, analyze, emit pipeline
Benchmarks Detailed performance methodology and results
Comparison Mapo vs AutoMapper, Mapperly, and Mapster
CLI Tool Standalone code generation CLI
Changelog Release history

CLI Tool

For use outside the normal build pipeline (scripts, non-MSBuild toolchains, code inspection):

dotnet tool install --global Mapo.Cli

mapo gen src/ Generated/

This scans C# files for [Mapper] classes and writes generated .g.cs files. The output is identical to what the source generator produces during dotnet build. See CLI Documentation for details.


Repository Structure

src/
  Mapo.Attributes/          Public API: [Mapper], [MapFrom], IMapConfig<S,T>, [MapDerived]
  Mapo.Generator/           Roslyn incremental source generator
  Mapo.Generator.CodeFixes/ IDE code fix provider for MAPO001 + MAPO003
tests/
  Mapo.Generator.Tests/     Unit tests (Roslyn compilation testing)
  Mapo.IntegrationTests/    Integration tests (runtime verification)
samples/
  Mapo.Sample/              Full e-commerce scenario
  Mapo.Benchmarks/          Performance comparison vs AutoMapper, Mapperly, Mapster
  Mapo.Circular/            Circular reference tracking demo
  Mapo.Polymorphic/         Polymorphic dispatch demo
  Mapo.Aot/                 NativeAOT compilation verification

Contributing

  1. Fork the repository
  2. Create a feature branch from dev
  3. Make your changes
  4. Run the full test suite:
    dotnet test tests/Mapo.Generator.Tests/ --configuration Release
    dotnet test tests/Mapo.IntegrationTests/ --configuration Release
    
  5. Open a pull request against main

Please ensure all existing tests pass and add tests for new functionality.


License

MIT

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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 was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

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.1 120 3/6/2026
1.1.0 100 3/5/2026
1.0.1 113 3/5/2026
1.0.0 111 3/5/2026