Architecture
Mapperly is an incremental .NET source generator implementation. Source generators are explained here and here.
Solution
benchmarks
Benchmarks to analyze the performance of the generated code and the source generator itselfbuild
Build scriptsdocs
Documentation of Mapperlysamples
Sample implementations of Mappers using Mapperlysrc
Source code of MapperlyRiok.Mapperly
The source generator implementationRiok.Mapperly.Abstractions
Abstractions and attributes to be used by the application code to configure Mapperly. This is referenced by the source generator but is not needed at runtime (except for some features, e.g., reference handling).
test
Unit- and integration tests of Mapperly
Flow
This describes the process implemented by Mapperly on a higher level.
For each discovered MapperAttribute
a new DescriptorBuilder
is created.
The DescriptorBuilder
is responsible to build a MapperDescriptor
which holds all the mappings.
The DescriptorBuilder
does this by following this process:
- Extracting the configuration from the attributes
- Extracting user implemented and user defined mapping methods.
It instantiates a
User*Mapping
(eg.UserDefinedNewInstanceMethodMapping
) for each discovered mapping method and adds it to the queue of mappings to work on. - Extracting user implemented object factories
- Extracting user implemented format providers
- Extracting external mappings
- For each mapping in the queue the
DescriptorBuilder
tries to build its implementation bodies. This is done by a so called*MappingBodyBuilder
. A mapping body builder tries to map each property from the source to the target. To do this, it asks theDescriptorBuilder
to create mappings for the according types. To create a mapping from one type to another, theDescriptorBuilder
loops through a set of*MappingBuilder
s. Each of the mapping builders try to create a mapping (anITypeMapping
implementation) for the asked type mapping by using one approach on how to map types (eg. an explicit cast is implemented by theExplicitCastMappingBuilder
). These mappings are queued in the queue of mappings which need the body to be built (currently body builders are only used for object to object (property-based) mappings). - The
SourceEmitter
emits the code described by theMapperDescriptor
and all its mappings. The syntax objects are created by usingSyntaxFactory
andSyntaxFactoryHelper
. TheSyntaxFactoryHelper
tries to simplify creating formatted syntax trees. If indentation is needed, theSyntaxFactoryHelper
instance of theSourceEmitterContext
/TypeMappingBuildContext
can be used.
Roslyn multi targeting
Mapperly targets multiple Roslyn versions by building multiple NuGet packages and merging them together into a single one. Multi-targeting is needed to support new language features, such as required members introduced in C# 11, while still supporting older compiler versions.
See build/package.sh
for details.
To introduce support for a new roslyn version see common tasks.
C# language features
The Mapperly source generator targets .netstandard2.0
but uses the latest C# language version
and polyfills generated by Meziantou.Polyfill
.
Some newer C# language features require new runtime features and therefore cannot be used in Mapperly.
A good C# language features requirements overview is available here.