Mapperize 0.1.1

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

Mapperize

A blazing-fast, compile-time, reflection-free object mapper for .NET. A safer, faster, AOT/trim-friendly alternative to AutoMapper — powered by a Roslyn source generator.

CI NuGet License: MIT


Why Mapperize?

Traditional mappers such as AutoMapper build mapping logic at runtime using reflection and compiled expression trees. That has three costs: a warm-up penalty, incompatibility with Native AOT / trimming, and — worst of all — mistakes are only discovered at runtime.

Mapperize does the work at compile time. You declare partial mapping methods; the source generator writes the implementations as plain member assignments. What you ship is exactly the code you would have written by hand.

AutoMapper Mapperize
When mapping is built Runtime (reflection + expression trees) Compile time (source generator)
Runtime reflection Yes None
Startup / warm-up cost Yes (config + first-map JIT) Zero
Native AOT / trimming Fragile Fully supported
Wrong/typo'd mappings Throw at runtime Reported at build time (diagnostics)
Debuggable output Opaque delegates Readable generated C# you can step into
Dependencies Several Zero (a single, dependency-free package)

Install

dotnet add package Mapperize

Targets netstandard2.0, so it works on .NET Framework 4.6.1+, .NET Core, and .NET 5–10.

Quick start

using Mapperize;

public class User
{
    public int Id { get; set; }
    public string FullName { get; set; }
    public int Age { get; set; }
    public Address Address { get; set; }
    public List<Order> Orders { get; set; }
}

public class UserDto
{
    public int Id { get; set; }
    public string Name { get; set; }       // renamed from FullName
    public long Age { get; set; }          // widened automatically
    public AddressDto Address { get; set; } // nested — mapped automatically
    public List<OrderDto> Orders { get; set; }
}

[Mapper]
public partial class UserMapper
{
    [MapProperty(nameof(User.FullName), nameof(UserDto.Name))]
    public partial UserDto ToDto(User user);
}

Usage:

var mapper = new UserMapper();
UserDto dto = mapper.ToDto(user);

That’s it. Address and Orders are discovered and mapped automatically — you don’t need to declare a method for every nested type (though you can, and it will be reused).

The generated code

The generator emits ordinary, readable C# (simplified):

public partial UserDto ToDto(User user)
{
    if (user is null) return default;
    return new UserDto
    {
        Id = user.Id,
        Name = user.FullName,
        Age = user.Age,
        Address = user.Address is null ? default : Map_1(user.Address),
        Orders = user.Orders is null ? default
            : System.Linq.Enumerable.ToList(System.Linq.Enumerable.Select(user.Orders, x => Map_2(x))),
    };
}

Features

  • Flat property mapping by name (case-insensitive by default).
  • Renames via [MapProperty("Source", "Target")].
  • Ignore a target via [MapperIgnoreTarget("Target")].
  • Nested objects — mapped recursively; helper methods are generated and de-duplicated.
  • CollectionsList<T>, arrays, HashSet<T>, and the read-only/interface variants (IEnumerable<T>, IReadOnlyList<T>, ICollection<T>, …).
  • Enums — by name (default, order-independent) or by value.
  • Nullable value typesint?int and back, handled safely.
  • Numeric conversions — implicit widening and explicit narrowing.
  • Constructors & records — positional records and constructor-only types are supported.
  • Compile-time diagnostics — unmapped members become build warnings (or errors, if you choose).
  • Zero runtime dependencies and full Native AOT / trimming support.

Configuration

Everything is configured on the [Mapper] attribute:

[Mapper(
    CaseInsensitive = true,                               // match member names ignoring case (default)
    UnmappedMemberBehavior = UnmappedMemberBehavior.Warn, // Ignore | Warn (default) | Error
    EnumMappingStrategy = EnumMappingStrategy.ByName)]     // ByName (default) | ByValue
public partial class UserMapper
{
    public partial UserDto ToDto(User user);
}

Set UnmappedMemberBehavior = UnmappedMemberBehavior.Error to make an accidental un-mapped property fail the build — turning a whole class of silent runtime bugs into compile errors.

Diagnostics

ID Meaning
MPZ001 A target member has no matching source member (warning or error).
MPZ002 A source and target member exist but no conversion is possible.
MPZ003 A mapping method has an unsupported signature.
MPZ004 The mapper type is generic or nested (not supported).

Performance

Mapping is generated as direct assignments, so throughput matches hand-written code and there is no startup cost. Indicative in-process measurements (.NET 8, single object with a nested object + a 10-item list; run dotnet run -c Release --project benchmarks/Mapperize.Benchmarks -- --quick):

Mapper Time Allocated
Hand-written ~250 ns 776 B
Mapperize ~246 ns 792 B
AutoMapper ~335 ns 896 B

Mapperize is on par with hand-written code, ~25–30% faster than AutoMapper on single-object maps, and allocates less in every scenario measured. For rigorous, isolated numbers run the full BenchmarkDotNet suite:

dotnet run -c Release --project benchmarks/Mapperize.Benchmarks

Security

  • No runtime reflection, no dynamic code generation, no expression compilation — nothing to exploit or to break under trimming/AOT.
  • Deterministic, auditable output: the mapping code is committed-grade C# you can read and diff.
  • For contrast, the AutoMapper version used in the benchmark project (13.0.1) carries a published high-severity advisory (GHSA-rvv3-g6hj-g44x). Mapperize ships zero runtime dependencies, so its supply-chain surface is minimal.

How it works

Mapperize is a single NuGet package that contains two things:

  1. A tiny runtime assembly with the attributes ([Mapper], [MapProperty], …).
  2. A Roslyn incremental source generator (shipped under analyzers/) that implements your partial methods during compilation.

There is no runtime engine — after compilation the attributes aren’t even needed.

Building & testing

dotnet build -c Release          # build everything
dotnet test  -c Release          # run the xUnit suite
dotnet run   -c Release --project samples/Mapperize.Sample   # runnable feature tour

Roadmap

  • User-defined member expressions / value converters
  • Flattening (Order.Customer.NameCustomerName)
  • before/after mapping hooks
  • Deep-copy option for same-type nested references
  • Mapping to an existing instance (void Update(Source, Target))

Contributions welcome — see the issues on GitHub.

License

MIT © 2026 Hovhannes Stepanyan. See LICENSE.

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
0.1.1 39 9/9/2026
0.1.0 42 9/9/2026