NMapper 2.1.2-pre

This is a prerelease version of NMapper.
There is a newer version of this package available.
See the version list below for details.
dotnet add package NMapper --version 2.1.2-pre
                    
NuGet\Install-Package NMapper -Version 2.1.2-pre
                    
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="NMapper" Version="2.1.2-pre" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="NMapper" Version="2.1.2-pre" />
                    
Directory.Packages.props
<PackageReference Include="NMapper" />
                    
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 NMapper --version 2.1.2-pre
                    
#r "nuget: NMapper, 2.1.2-pre"
                    
#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 NMapper@2.1.2-pre
                    
#: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=NMapper&version=2.1.2-pre&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=NMapper&version=2.1.2-pre&prerelease
                    
Install as a Cake Tool

NMapper

Version Downloads Buy Me a Coffee

NMapper is a lightweight, explicit object mapping library for .NET. It favours clear, testable mapping code over configuration and conventions.

Key Features

  • Explicit mapping classes written in plain C#
  • One-way and two-way mappings.
  • Supports nested mappings.
  • Automatic mapping of collections and arrays.
  • Clear compile-time errors instead of runtime surprises.
  • No conventions, no reflection-based property mapping, no magic.
  • Designed to use with dependency injection (Microsoft.Extensions.DependencyInjection).

Philosophy

Mapping is application logic. NMapper treats mappings as first-class code rather than configuration. Every mapping is explicit, discoverable, and refactor-safe.

NMapper intentionally avoids automatic property matching and hidden behavior in favor of clarity, control, and debuggability.

Download and Install NMapper

This library is available on NuGet: https://www.nuget.org/packages/NMapper/ Use the following command to install NMapper using the NuGet Package Manager Console:

PM> Install-Package NMapper

You can use this library in any .NET project which is compatible to .NET Standard 2.0 and higher.

API Usage

Define a Mapping

A mapping is a concrete specificiation of a source-to-target type conversion. Mappings are defined as simple C# classes by implementing IMapping<TSource, TTarget>.

 public class PersonMapping :
        IMapping<Person, PersonDto>,
        IMapping<PersonDto, Person>
{
    public PersonDto Map(Person person) => new PersonDto
    {
        Id = person.Id,
        Name = person.Name,
    };

    public Person Map(PersonDto personDto) => new Person
    {
        Id = personDto.Id,
        Name = personDto.Name,
    };
}

Nested Mappings

If a mapping needs to delegate to other mappings, implement IMappingWithContext<TSource, TTarget>. This interface gives you the extra parameter IMappingContext which allows to run further mappings.

public class OrderMapping : IMappingWithContext<Order, OrderDto>
{
    public OrderDto Map(Order source, IMappingContext context) => new()
    {
        Id = source.Id,
        Customer = context.Map<CustomerDto>(source.Customer)
    };
}

Register Mappings

Each Mapper instance can be configured with 1-N mappings.

Register Mappings manually

The constructor of Mapper allows to specify mappings directly.

var mappings = new IMapping[]
{
    new PersonMapping(),
    new CountryMapping(),
};
IMapper mapper = new Mapper(mappings);
Register Mappings via Dependency Injection

Mappings can be registered via dependency injection. Use the AddMapping extension methods on your DI service collection. From there you have multiple ways to register/scan mappings:

services.AddMapping(o =>
{
    // Register all mappings from a specific assembly:
    o.Mappings.ScanAssembly(typeof(Person).Assembly);

    // Register mappings manually
    o.Mappings.Add(new IMapping[] { new PersonMapping(), new VenueMapping() });
});

Perform Mappings

Create a new instance of Mapper or inject IMapper via dependency injection and use it to perform mappings.

var personDto = mapper.Map<PersonDto>(person);

Mapping Collections and Arrays

Collections and arrays are mapped automatically as long as an element mapping exists.

var personDtos = mapper.Map<IEnumerable<PersonDto>>(persons);

The concrete collection instances (arrays and lists) are created using an ICollectionFactory. By default, NMapper uses an internal FastCollectionFactory, which is optimized for performance. You can override this behavior via MapperOptions.CollectionFactory.

Recursion Handling (Circular Object Graphs)

By default, NMapper does not track object references during mapping. This keeps the mapper fast and allocation-free for simple object graphs. For object graphs that contain circular references (e.g. parent-child relationships with back-references), recursion handling can be enabled.

var mapperOptions = new MapperOptions
{
    EnableRecursionHandling = true
};

When enabled, NMapper tracks previously mapped source objects and reuses them internally to avoid infinite recursion and stack overflows.

Enabling recursion handling has a measurable runtime cost and should only be enabled when required.

Maximum Depth

In addition to reference tracking, a maximum traversal depth can be configured:

var mapperOptions = new MapperOptions
{
    EnableRecursionHandling = true,
    MaxDepth = 10,
    ThrowIfMaxDepthExceeded = true
};

MaxDepth = 0 disables depth checking (default). When ThrowIfMaxDepthExceeded is enabled, the mapper throws a MappingException once the depth limit is exceeded.

Per-Call Mapping Options

Some options are also available on a per-call basis. This allows you to enable recursion handling for specific mapping calls only while using the performance advantage for the rest of the mappings.

var venueDto = mapper.Map<VenueDto>(venue, o => o.EnableRecursionHandling = true);

Exceptions

NMapper uses explicit, strongly typed exceptions to make mapping errors easy to diagnose. All exceptions are thrown at runtime and indicate configuration or mapping logic errors.

Exception Description
DuplicateMappingException Thrown when more than one mapping is registered for the same source and target type. Each source → target pair must be unique.
MissingMappingException Thrown when no mapping exists for the requested source and target type and no built-in primitive conversion applies.
MappingException Thrown when an error occurs during execution of a mapping. This exception wraps the original exception and adds source type, target type, and mapping type information.
AggregateException When multiple nested mappings fail during a single mapping operation, NMapper may throw an AggregateException containing one or more of the exceptions listed above. This behavior allows all mapping errors to be reported at once instead of failing on the first error.
StackOverflowException Detected by the .NET runtime. Typically happens when a parent-child object graph with back-references is used while recursion handling is disabled. Set EnableRecursionHandling = true and try again.

Thank You

A big thank you to all the people who have contributed to this project! If you find a bug or want to propose a new feature, feel free to open an issue on GitHub.

We'd also like to thank nabinked for leaving us the project name and working title NMapper.

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 is compatible. 
.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.

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
2.2.0-pre 97 4/2/2026
2.1.13 91 4/2/2026
2.1.11-pre 89 4/2/2026
2.1.9-pre 82 4/2/2026
2.1.8-pre 90 3/30/2026
2.1.7-pre 85 3/29/2026
2.1.6-pre 82 3/29/2026
2.1.5-pre 92 3/27/2026
2.1.4-pre 85 3/27/2026
2.1.3-pre 81 3/25/2026
2.1.2-pre 99 2/5/2026
2.1.1-pre 144 1/24/2026
2.1.0-pre 94 1/24/2026
2.0.23 115 1/24/2026
2.0.21-pre 99 1/22/2026
2.0.20-pre 102 1/22/2026
2.0.19-pre 103 1/15/2026
2.0.18-pre 100 1/11/2026
2.0.17-pre 97 1/11/2026
2.0.16-pre 106 1/9/2026
Loading failed

2.0
- New mapper IMapper and mapping interfaces IMapping<TSource, TTarget>.
- Handle circular references during mapping.

1.0
- Initial release by nabinked.