๐บ๏ธ Mappa: the source generator C# mapper
Mappa (italian for map) is a .NET source generator for C#. Mappa allows to automatically generate mapper between differrent types, similarly to what AutoMapper does but the mapping generation happens at compile time.
Why Mappa?
Mappa is relatively new project (well I have been workig on this for a couple of year) and does not aim at replacing bigger players in this field, like AutoMapper. So why create a new mapping tool? Well because there was no automatic mapper that was satisying my needs:
- I needed to be able to generate Native AOT executable
- I needed to be able to easily share mapping code across different mappers
- I needed to be able to see and understand what the mapper was doing
- I needed a mapper that take into account protobuf
- I needed a mapper that was easier to cofigure, yet powerful
Mappa is all of this!
When to use Mappa?
Mappa is well suited when:
- You want to generate Native AOT executables
- You have complex mapping and want to understand what code is being generated
- You need to reuse some code across different mappers
Example
Consider the following code snipped:
using Mappa;
using System.Collections.Generic;
namespace Sample;
public enum MyEnumeration
{
One,
Two,
Three,
}
public class Source
{
public int PropertyA {get;set;}
public int[] PropertyB {get;set;}
public MyEnumeration PropertyC {get;set;}
}
public class Target
{
public long PropertyA {get;set;}
public List<string> PropertyB {get;set;}
public string PropertyC {get;set;}
}
[Mappa]
public partial class Mapper
{
public partial Target Map(Source input);
}
will create mapping code like the following:
namespace Sample;
public partial class Mapper
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("Mappa", "0.0.1.0")]
public partial Sample.Target Map(Sample.Source input)
{
long __mappa_tmp_1 = input.PropertyA;
int[] __mappa_tmp_2 = input.PropertyB;
System.Collections.Generic.List<string> __mappa_tmp_3 = new System.Collections.Generic.List<string>(__mappa_tmp_2.Length);
for (int __mappa_tmp_3 = 0; __mappa_tmp_3 < __mappa_tmp_2.Length; ++__mappa_tmp_3)
{
int __mappa_tmp_4 = __mappa_tmp_2[__mappa_tmp_3];
string __mappa_tmp_5 = __mappa_tmp_4.ToString();
__mappa_tmp_3.Add(__mappa_tmp_5)
}
Sample.MyEnumeration __mappa_tmp_6 = input.PropertyC;
string __mappa_tmp_7;
switch(__mappa_tmp_6)
{
case Sample.MyEnumeration.One:
__mappa_tmp_7 = "One";
break;
case Sample.MyEnumeration.Two:
__mappa_tmp_7 = "Two";
break;
case Sample.MyEnumeration.Three:
__mappa_tmp_7 = "Three";
break;
default:
throw new System.OutOfRangeException(nameof(__mappa_tmp_6));
}
Sample.Target __mappa_tmp_8 = new Sample.Target()
{
PropertyA = __mappa_tmp_1,
PropertyB = __mappa_tmp_3,
PropertyC = __mappa_tmp_7;
}
return __mappa_tmp_8;
}
}
Whatโs next?
More feature are going to be added in future releases:
- Polymorphysm
- Allow the user to prefer arrays over list when mapping towards generic interfaces
- Improve performances by allowing users to map using
Span<T>
and friends - More default mappings (e.g.
byte[]
<->Guid
) - More types supported (e.g.
ValueTuple<T>
) - Union types (when they will be released in .NET)
- More support for MappaContext
- Dependency via static class provided by Mappa Settings
- Allow users to use
Add
method instead than using theIndexer
when mapping dictionaries - Add default rules to select the source property
- Support mapping to/from fields
NuGet packages
Mappa provide 6 NuGet packeges:
- Mappa: source generator that allows to automatically generate mapping between classes and value types;
- Mappa source generator: source generator that allows to automatically generate mapping between classes and value types;
- Mappa Protobuf: methods to map
Google.Protobuf.WellKnownTypes
objects from Google.Protobuf package into common objects. - Mappa Protobuf dependency: utility methods to register the Protobuf mapper.
- Mappa Bson: methods to map
MongoDB.Bson
objects from MongoDB.Bson package into common objects. - Mappa Bson dependency: utility methods to register the Bson mapper.