Installation
You can install the core package directly from Nuget NeatMapper.
Creating maps
You have to create one or more classes implementing one of the following mapping interfaces:
INewMap<TSource, TDestination>
to map existing objects to new onesIMergeMap<TSource, TDestination>
to map and merge objects with othersIMatchMap<TSource, TDestination>
to match objects together (used to merge collections)IHierarchyMatchMap<TSource, TDestination>
likeIMatchMap<TSource, TDestination>
but matches both exact types and derived onesIProjectionMap<TSource, TDestination>
to project objects into new ones, 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 instead:
INewMapStatic<TSource, TDestination>
IMergeMapStatic<TSource, TDestination>
IMatchMapStatic<TSource, TDestination>
IHierarchyMatchMapStatic<TSource, TDestination>
IProjectionMapStatic<TSource, TDestination>
IAsyncNewMapStatic<TSource, TDestination>
IAsyncMergeMapStatic<TSource, TDestination>
If you create a class with more than 1 implementation 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{ ... };
}
}
Configuring 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>();
Mapping objects
Map your objects by invoking the generic (extension) methods available:
IMapper
mapper.Map<Destination>(source)
mapper.Map<Source, Destination>(source)
mapper.Map(source, destination)
mapper.Map<Source, Destination>(source, destination)
IEnumerable
/IEnumerable<T>
extension methods:enumerable.Project<Destination>(mapper)
enumerable.Project<Source, Destination>(mapper)
IAsyncMapper
await asyncMapper.MapAsync<Destination>(source)
await asyncMapper.MapAsync<Source, Destination>(source)
await asyncMapper.MapAsync(source, destination)
await asyncMapper.MapAsync<Source, Destination>(source, destination)
IAsyncEnumerable<T>
extension methodasyncEnumerable.Project<Source, Destination>(asyncMapper)
IProjector
projector.Project<Source, Destination>()
IQueryable
/IQueryable<T>
extension methods:queryable.Project<Destination>(projector)
queryable.Project<Source, Destination>(projector)
Note that mapping matches types exactly, so parent or derived classes won’t work.
// Create a new object (source type is auto-inferred)
var myProductDto = mapper.Map<ProductDto>(myProduct);
// Map to an existing object asynchronously (both types are auto-inferred)
await asyncMapper.MapAsync(myCategory, myCategoryDto);
// Create a projection to use in a LINQ query
var myBookDtos = db.Set<Book>()
.Project<BookDto>(projector)
.ToArray();