Skip to main content

NextGenMapper by Anton Ryabchikov

Nuget / site data

Nuget GitHub last commit GitHub Repo stars

Details

Info

info

Name: NextGenMapper

Package Description

Author: Anton Ryabchikov

NuGet: https://www.nuget.org/packages/NextGenMapper/

You can find more details at https://github.com/DedAnton/NextGenMapper

Source : https://github.com/DedAnton/NextGenMapper

Original Readme

note

License: MITGitHub release (latest by date including pre-releases)donate

Extremely fast and lightweight minimalistic object mapper generated on the fly

https://user-images.githubusercontent.com/36799941/191618500-31f7e179-3510-49dc-ad13-18e07de8309b.mov

Key features

  • Generation of mapping methods on the fly
  • Reflection and expression trees are not used
  • Performance like a hand-written mapper
  • Minimum memory allocation
  • Does not increase application startup time
  • No dependencies in the final assembly
  • No third party tools and IDE dependencies
  • Static analysis support
  • Code navigation support
  • Easy to debug
  • No attributes and fluid API

NextGenMapper is a tool that just solves a problem and tries not to create new ones

Usage

Add using NextGenMapper and call the Map extension method on the object you want to map

using NextGenMapper;

var source = new Source("Anton", 25);

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

Console.WriteLine(destination);

record Source(string Name, int Age);
record Destination(string Name, int Age);

To customize the mapping of certain properties, call the MapWith method and pass the value of the overridden property as an argument

using NextGenMapper;

var source = new Source("Anton", "Ryabchikov", 25);

var destination = source.MapWith<Destination>(name: source.FirstName + ' ' + source.LastName);

Console.WriteLine(destination);

record Source(string FirstName, string LastName, int Age);
record Destination(string Name, int Age);

In order for NextGenMapper to use your mapping when mapping other objects, you need to create a partial class Mapper in the NextGenMapper namespace and add the Map method with your implementation to it

namespace NextGenMapper;

internal static partial class Mapper
{
internal static Destination Map<To>(this Source source)
=> source.MapWith<Destination>(name: source.FirstName + ' ' + source.LastName);
}

The following collection types are currently supported: List<T>, Array<T>, ICollection<T>, IEnumerable<T>, IList<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ImmutableArray<T>, ImmutableList<T>, IImmutableList<T>

var sourceCollection = new List<Source> { new("Anton", 25) };

var destination = sourceCollection.Map<List<Destination>>();

Enums can also be mapped

var source = Source.EnumValue;

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

Projection for IQueryable supported

_dbContext.Users.Project<UserDestination>().ToList();

Note: Due to the use of new technology, some versions of Visual Studio can sometimes experience problems with syntax highlighting if IntelliCode says an error, but the solution was build without errors is to simply restart Visual Studio

Installation

Install from the package manager console:

PM> Install-Package NextGenMapper -prerelease

Or from the .NET CLI as:

dotnet add package NextGenMapper --prerelease

How it works?

NextGenMapper uses the new C# language feature - Source Code Generators. You can describe the work of the Source Code Generator in the following steps:

  1. Code compiles
  2. The source code generator analyzes the assembly
  3. Generates new code based on analysis
  4. Compiles the new code and adds it to the assembly

This is how the method that is called initially looks like:

internal static To Map<To>(this object source) => throw new InvalidOperationException($""Error when mapping {source.GetType()} to {typeof(To)}, mapping function was not found. Create custom mapping function."");

When we call it, the generator analyzes this call and generates a mapping function:

internal static Destination Map<To>(this Source source) 
=> new Destination(source.Name, source.Age);

The trick is that the method signatures are identical, but the generated method has more specific parameters and fits better, so it is called (this behavior is described in the specification)

Status

At the moment, all the main functionality has been added. But the work isn't over yet.

All tasks and their progress can be viewed on the project board

About

note

Automating generating mapping between classes

How to use

Example ( source csproj, source files )

This is the CSharp Project that references NextGenMapper

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="NextGenMapper" Version="0.1.0-alpha.13" OutputItemType="Analyzer" />
</ItemGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
</Project>

Generated Files

Those are taken from $(BaseIntermediateOutputPath)\GX

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace NextGenMapper.Extensions
{
internal static class MapperExtensions
{
/// <summary>
/// Do not use this method, for auto-generated mapper only!
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryGetSpan<TSource>(this IEnumerable<TSource> source, out ReadOnlySpan<TSource> span)
{
bool result = true;
if (source.GetType() == typeof(TSource[]))
{
span = Unsafe.As<TSource[]>(source);
}
#if NET5_0_OR_GREATER
else if (source.GetType() == typeof(List<TSource>))
{
span = CollectionsMarshal.AsSpan(Unsafe.As<List<TSource>>(source));
}
#endif
else
{
span = default;
result = false;
}

return result;
}
}
}

Usefull

Download Example (.NET C# )

Share NextGenMapper

https://ignatandrei.github.io/RSCG_Examples/v2/docs/NextGenMapper

In the same category (Mapper) - 7 other generators

AutoDTO

AutoGen

DynamicsMapper

LightweightObjectMapper

MagicMap

mapperly

MapTo