NeatMapper 2.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package NeatMapper --version 2.2.0                
NuGet\Install-Package NeatMapper -Version 2.2.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="NeatMapper" Version="2.2.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add NeatMapper --version 2.2.0                
#r "nuget: NeatMapper, 2.2.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.
// Install NeatMapper as a Cake Addin
#addin nuget:?package=NeatMapper&version=2.2.0

// Install NeatMapper as a Cake Tool
#tool nuget:?package=NeatMapper&version=2.2.0                

.NEaT Mapper

NuGet

What is this package

.NEaT Mapper is an object mapper (and now projector too!), with configurable and reusable mappings.

This allows you to create mappings (and projections) between different types (even generic ones), combine them, nest them and reuse them, making your code DRY. Map once, use everywhere.

All of this is achieved with explicit strongly typed maps, easily debuggable, no implicit mappings, no conventions, no compilation into obscure expressions, no black boxes.

It also supports asynchronous maps and services via Dependency Injection (DI).

How to install

You can install this package directly from Nuget https://www.nuget.org/packages/NeatMapper

How to use

1. Create mapping classes

You have to create one or more classes implementing one of the following mapping interfaces:

  • INewMap<TSource, TDestination> to map existing objects to new ones
  • IMergeMap<TSource, TDestination> to map and merge an object with another one
  • IProjectionMap<TSource, TDestination> to project an object into another one, this will create an expression which can be used with LINQ or compiled into a NewMap

You can also create async maps by implementing the interfaces:

  • IAsyncNewMap<TSource, TDestination>
  • IAsyncMergeMap<TSource, TDestination>

If you are on .NET 7 or greater you can use the static versions of the interfaces above: INewMapStatic<TSource, TDestination>, IMergeMapStatic<TSource, TDestination>, IProjectionMapStatic<TSource, TDestination>, IAsyncNewMapStatic<TSource, TDestination>, IAsyncMergeMapStatic<TSource, TDestination>.

If you create a class with more than 1 mapping of the same interface you must implement them explicitly like below.

public class MyMaps :
    INewMap<Product, ProductDto>,
    IAsyncMergeMap<Category, CategoryDto>,
    IProjectionMap<Book, BookDto>
{
    ProductDto? INewMap<Product, ProductDto>.Map(Product? source, MappingContext context){
        if(source == null)
            return null;
        else{
            return new ProductDto{
                Code = source.Code,
                ...
            };
        }
    }

    async Task<CategoryDto?> IAsyncMergeMap<Category, CategoryDto>.MapAsync(Category? source, CategoryDto? destination, AsyncMappingContext context){
        if(source != null){
            destination ??= new CategoryDto();
            destination.Id = source.Id;
            destination.Parent = await context.Mapper.MapAsync(source.Parent, destination.Parent, context.CancellationToken);
            ...
        }
        return destination;
    }

    Expression<Func<Book, BookDto>> IProjectionMap<Book, BookDto>.Project(ProjectionContext context){
        return source => source == null ? null : new BookDto{ ... };
    }
}

2. Configure the services

The easiest way to create a mapper is to use Dependency Injection (DI), which will handle all the configuration for you.

// Add all available maps
services.Configure<CustomMapsOptions>(o => o.TypesToScan = Assembly.GetExecutingAssembly().GetTypes().ToList() );
// Or add specific maps
//services.Configure<CustomMapsOptions>(o => o.TypesToScan = new List<Type>{ typeof(MyMaps), ... });

services.AddNeatMapper();

...

IMapper mapper = serviceProvider.GetRequiredService<IMapper>();
IAsyncMapper asyncMapper = serviceProvider.GetRequiredService<IAsyncMapper>();
IProjector projector = serviceProvider.GetRequiredService<IProjector>();

3. Map your types

Map your types by invoking the generic methods available.

Note that mapping matches types exactly, so parent or derived classes won't work.

// Create a new object
var myProductDto = mapper.Map<ProductDto>(myProduct);

// Map to an existing object asynchronously (the types are auto-inferred)
await asyncMapper.MapAsync(myCategory, myCategoryDto);

// Create a projection to use in a LINQ query
var myBookDtos = db.Set<Book>()
    .Select(projector.Project<IQueryable<Book>, IQueryable<BookDto>>())
    .ToArray();

Advanced options

Find more advanced use cases in the wiki or in the extended tests project.

License

Read the license here

Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 is compatible.  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 is compatible.  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. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 is compatible. 
.NET Standard netstandard2.1 is compatible. 
.NET Framework net47 is compatible.  net471 was computed.  net472 was computed.  net48 is compatible.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen 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 (2)

Showing the top 2 NuGet packages that depend on NeatMapper:

Package Downloads
NeatMapper.EntityFrameworkCore

Creates automatic maps and projections between entities and their keys (even composite and shadow keys), supports normal maps and asynchronous ones, also supports collections (not nested).

NeatMapper.Transitive

Allows mapping types by automatically chaining maps together, eg: If you have maps for types A -> B and B -> C you can also map A -> C by chaining A -> B -> C, supports normal maps and asynchronous ones, also supports collections.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
5.0.0 125 11/3/2024
4.0.0 139 7/16/2024
3.1.0 149 4/26/2024
3.0.0 113 3/28/2024
2.2.0 165 2/3/2024
2.1.0 273 12/5/2023
2.0.0 219 11/12/2023
1.1.0 152 10/2/2023
1.0.2 153 10/2/2023