Mappy.dotNet 4.0.0

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

🍁Mappy 4.0

Static Badge NuGet Version NuGet Downloads License

Mappy is a lightweight, convention-first object mapper for modern .NET.

It keeps the common case simple:

var dto = entity.Map<EntityDto>();

Mappy 4.0 focuses on predictable mapping, cached mapping plans, compiled property accessors, nested objects, collections, immutable constructor-based types, circular-reference preservation, explicit configuration, converters, and mapping into existing objects.

Why Mappy?

  • Simple API with no mandatory configuration
  • Cached mapping plans per source/destination pair
  • Compiled property getters and setters
  • Nested object mapping
  • Collection and array mapping
  • Constructor mapping for immutable DTOs and records
  • Circular and shared-reference preservation
  • Explicit property rename and ignore configuration
  • Explicit type converters
  • MapTo for updating existing objects
  • Detailed MappingException errors
  • Targets .NET 8, 9, and 10
  • No external runtime dependencies

Installation

dotnet add package Mappy.dotNet --version 4.0.0

Basic mapping

var source = new User
{
    Id = 1,
    Name = "Manoj",
    Email = "manoj@example.com"
};

var dto = source.Map<UserDto>();

Properties with matching names and compatible types are mapped automatically.

Nested mapping

var dto = order.Map<OrderDto>();

Mappy recursively maps compatible nested objects:

Order
 └── Customer
      ↓
OrderDto
 └── CustomerDto

Collections

var result = users.MapCollection<UserDto>();

Arrays are also supported by the mapping engine:

UserDto[] result = users
    .MapCollection<UserDto>()
    .ToArray();

Supported destination collection shapes include arrays, List<T>, HashSet<T>, and compatible generic collection interfaces such as IEnumerable<T>, ICollection<T>, IList<T>, and IReadOnlyCollection<T>.

Rename properties

Use strongly typed configuration when source and destination names differ:

var config = new MappingConfiguration()
    .Map<User, UserDto>(
        source => source.FullName,
        destination => destination.Name);

var dto = user.Map<UserDto>(config: config);

The original string-based configuration API is also retained:

var config = new MappingConfiguration();

config.AddPropertyMapping(
    typeof(User),
    typeof(UserDto),
    "FullName",
    "Name");

Ignore properties

var config = new MappingConfiguration()
    .Ignore<User, UserDto>(x => x.PasswordHash);

var dto = user.Map<UserDto>(config: config);

Or:

config.ExcludeProperty(
    typeof(User),
    typeof(UserDto),
    "PasswordHash");

Explicit converters

Mappy intentionally avoids broad implicit conversions. Register conversions explicitly:

var config = new MappingConfiguration()
    .AddConverter<Guid, string>(
        value => value.ToString("N"));

var dto = entity.Map<EntityDto>(config: config);

This keeps type behavior predictable.

Mapping into an existing object

For update scenarios:

request.MapTo(entity);

Optional mapping options are supported:

request.MapTo(
    entity,
    options: new MappingOptions
    {
        IgnoreNullValues = true
    });

This is useful for PATCH-style updates where null values should leave existing destination values unchanged.

Immutable types and records

Mappy 4.0 can map constructor parameters when a destination does not have a parameterless constructor:

public sealed class User
{
    public string Name { get; set; } = "";
    public int Age { get; set; }
}

public sealed class UserDto(string name, int age)
{
    public string Name { get; } = name;
    public int Age { get; } = age;
}

Then:

var dto = user.Map<UserDto>();

Circular references

Mappy 4.0 preserves object identity by default.

For:

Parent
 └── Child
      └── Parent

the mapped graph can retain the same relationship:

var result = source.Map<Destination>();

ReferenceEquals(
    result,
    result.Child.Parent);

Returns true.

The legacy boolean API remains available:

var result = source.Map<Destination>(
    handleCircularReferences: false);

For more control:

var options = new MappingOptions
{
    PreserveReferences = true
};

Private properties

For compatibility with earlier Mappy releases, non-public instance properties remain supported by default.

You can explicitly disable them:

var options = new MappingOptions
{
    IncludeNonPublicProperties = false
};

var dto = source.Map<UserDto>();

Asynchronous custom mapping

Normal object mapping is synchronous and does not introduce an unnecessary async pipeline.

Async is available when your custom mapping itself requires asynchronous work:

var dto = await source.MapAsync<UserDto>(async destination =>
{
    destination.DisplayName =
        await GetDisplayNameAsync(source.Id);
});

For collections:

var result = await users.MapCollectionAsync<UserDto>(
    async destination =>
    {
        destination.DisplayName =
            await GetDisplayNameAsync(destination.Id);
    });

Type safety

Mappy maps directly assignable or explicitly supported values.

For incompatible types:

public class Source
{
    public int Id { get; set; }
}

public class Destination
{
    public DateTime Id { get; set; }
}

mapping fails with a MappingException instead of silently performing an unexpected conversion.

For intentional conversions, register a converter.

Performance

Mappy 4.0 separates mapping-plan construction from mapping execution.

The first mapping for a source/destination pair builds and caches metadata:

Source + Destination
        ↓
Mapping plan
        ↓
Compiled property accessors
        ↓
Cached
        ↓
Fast repeated mapping

Property getters and setters are compiled once rather than using PropertyInfo.GetValue and SetValue for every mapped property.

For trustworthy performance comparisons, the repository includes a dedicated benchmark project. Benchmarks should be run in Release mode on the target runtime and hardware rather than relying on a single stopwatch measurement.

Design goals

Mappy deliberately does not require:

  • a dependency injection container
  • a global service provider
  • a large configuration system
  • runtime source-generation tooling
  • implicit conversion of arbitrary types
  • external runtime packages

The goal is a small API with strong internals.

Target frameworks

Mappy targets:

  • .NET 8
  • .NET 9
  • .NET 10

License

Mappy is released under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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 is compatible.  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 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.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
4.0.0 48 9/15/2026
3.1.0 244 11/24/2025
3.0.0 265 5/18/2025
2.1.0 201 12/28/2024
2.0.1 182 12/20/2024
1.0.0 181 12/16/2024

Mappy 4.0 introduces cached mapping plans, compiled property accessors, explicit configuration, converters, MapTo, constructor mapping, reference preservation, improved collections, and detailed MappingException errors.