Mappa.Generator
10.0.0
dotnet add package Mappa.Generator --version 10.0.0
NuGet\Install-Package Mappa.Generator -Version 10.0.0
<PackageReference Include="Mappa.Generator" Version="10.0.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="Mappa.Generator" Version="10.0.0" />
<PackageReference Include="Mappa.Generator"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add Mappa.Generator --version 10.0.0
#r "nuget: Mappa.Generator, 10.0.0"
#:package Mappa.Generator@10.0.0
#addin nuget:?package=Mappa.Generator&version=10.0.0
#tool nuget:?package=Mappa.Generator&version=10.0.0
Mappa.Generator
This source generator generates code for partial methods in partial classes tagged with the [Mappa] attribute defined in the Mappa package.
The generated code allow to map from a source type to a target type.
Assuming you have a partial method like the following
[Mappa]
public partial class Mapper
{
public partial TTarget Map(TSource input);
}
where TSource is the source type of the mapping and TTarget is the target type of the mapping, the source generator works by applying the following set of strategies in the order they are defined (see TypeMapIdentifierAlgorithm.cs):
- <u>Polymorphic mapping</u>
- When:
- The method has one or multiple
[MappaTypeMapping]attributes
- The method has one or multiple
- What:
- The input type will determine how the mapping from
TSourcetoTTargetwill happen, - For every
[MappaTypeMapping]attributes a mapping is created, - The default mapping in case the actual parameter type does not match any of the source type from the
[MappaTypeMapping]attributes is determined by the[MappaTypeMappingDefault]attribute - if the attribute is not present the default behaviour will throw an exception.
- The input type will determine how the mapping from
- When:
- <u>Existing method strategy</u>
- When:
- A method in the same class or a base class of the mapper from
TSourcetoTTargetexists OR, - A method from a property or field marked with the
[MappaDependency]on the mapper or an accessible base class of the mapper, or from a base class of the dependency type fromTSourcetoTTargetexists OR, - A method from a type defined via the
[MappaStaticDependency]attribute exists OR, - A polymorphic method where one of the
[MappaTypeMapping]attributes matchesTSourceandTTargetOR, - Settings
PolymorphicMapMethodWithMatchingDefaultAttributeisEnableand a polymorphic method with attribute[MappaTypeMappingDefault]and behaviourMappaTypeMappingDefaultBehavior.MapSourceTypeandTTargetis matching the target type defined by the attribute andTSourcethe source type of the method exists;
- A method in the same class or a base class of the mapper from
- What:
- the method is invoked;
- Notes:
- This strategy is usually used when mapping element of an array, keys or values of dictionaries, elements of tuples, properties of class/struct/record.
- When:
- <u>Identity strategy</u>:
- When:
TSourceandTTargetare the same type (e.g.TSource => intandTTarget => int) OR,TSourcecan be implicitly converted intoTTarget(e.g.TSource => intandTTarget => long);
- What:
- the input value is simply assigned to the target;
- When:
- <u>Nullable strategy</u>:
- When:
TSourceis theNullable<T>value type (e.g.int?) OR,TSourceis anullablereference type when#nullable enable(e.g.string?) OR,TSourceis a reference type when#nullable disable(e.g.string),- AND a mapping exists from source to target when stripped of the nullablity;
- What:
- if
TTargetcan benullthe mapper will return null OR, - if
TTargetcannot benullthe mapper will throw aNullReferenceException;
- if
- When:
- <u>
enumstrategy</u>:- When:
TSourceis anenumandTTargetis a differentenum, an integral numeric type compatible with theenumor a string OR,TSourceis a differentenum, an integral numeric type compatible with theenumandTTargetis anenum;
- What:
- a
switchstatement is introduced to quickly mapTSourcetoTTargetusing all the possible values of theenum,
- a
- When:
- <u>
stringstrategy</u>:- When:
TSourceis astringandTTargetis any of the numeric types OR,TSourceis astringandTTargetis any of the following typesDateTime,DateTimeOffset,DateOnly,TimeOnly,Guid,UriOR,TTargetis astringORTSourceis astringandTTargetis any type with an accessible staticParsemethod;
- What:
TSourceis astringandTTargetis any of the numeric types then the relevantParsemethod will be invoked, possibly with the culture identified by theMappaSettingsattribute, if any is provided on the class or on the method;TSourceis astringandTTargetis any of the following typesDateTime,DateTimeOffset,DateOnly,TimeOnly,Guidthen theirTTarget.Parsemethod will be used, possibly with the format and culture identified by theMappaSettingsattribute, if any is provided on the class or on the method;TSourceis astringandTTargetisUrithen theSystem.UriBuilderwill be used for the mapping;TTargetis astringandTSourceis any of the following typesDateTime,DateTimeOffset,DateOnly,TimeOnly,Guidthen theirTSource.ToString()method will be used, possibly with the format and culture identified by theMappaSettingsattribute, if any is provided on the class or on the method;TTargetis astringandTSourceis any of the numeric types then the relevantToStringoverload will be used, possibly with the format and culture identified by theMappaSettingsattribute, if any is provided on the class or on the method;TTargetis astringthen theTSource.ToStringmethod will be used;TSourceis astringandTTargetis any type with an accessible staticParsemethod then theParsemethod is invoked (note: an existing constructor accepting only a single string parameter will take priority over this);
- When:
- <u>Date & Time strategy</u>:
- When:
TSourceis aDateTimeandTTargetislongor,DateTimeor,TimeOnlyOR,TSourceis aDateTimeOffsetandTTargetislongor,DateTimeor,DateTimeor,TimeOnlyOR,TSourceis aDateOnlyandTTargetislongor,DateTimeOR,TSourceis alongandTTargetisDateTimeor,DateTimeOffsetOR,TSourceis aTimeSpanandTTargetisdoubleOR,TSourceis adoubleandTTargetisTimeSpanOR,
- What:
- The usual mapping conversions are used;
- When mapping from
DateOnlytoDateTimeorDateTimeOffsettheTimeOnly.Zerois used; - When mapping to or from
longthe Unix time is used; - When a timezone is required UTC is implied;
- Notes:
- The mapping from
DateTimetoDateTimeOffsetis handled by the identify strategy;
- The mapping from
- When:
- <u>Container strategy</u>:
- When:
TSourceandTTargetare both either dictionaries or collections,- For dictionaries, mappings exist from source key type to the target key type and from the source value type to the target value type,
- For collections, a mapping exists from the source element type to the target element type,
TSourcedictionary types accepted:- any type implementing
IDictionary<TKey, TValue>; - any type implementing
IReadOnlyDictionary<TKey, TValue>; - any type implementing
IEnumerable<KeyValuePair<<TKey, TValue>>;
- any type implementing
TTargetdictionary types accepted:- any type implementing
IDictionary<TKey, TValue>that has a constructor with zero arguments; - the following interfaces:
IDictionary<TKey, TValue>,IReadOnlyDictionary<TKey, TValue>,IImmutableDictionary<TKey, TValue>; - the following classes:
ImmutableDictionary<TKey, TValue>,ImmutableSortedDictionary<TKey, TValue>,FrozenDictionary<TKey, TValue>,ConcurrentDictionary<TKey, TValue>;
- any type implementing
TSourcecollection types accepted: any type implementingIEnumerable<T>, arrays,Span<T>,ReadOnlySpan<T>,Memory<T>andReadOnlyMemory<T>;TTargetcollection types accepted:- any type implementing
ICollection<T>orISet<T>that has a constructor with zero arguments (or one constructor with one integer argument of typeintandMappaSettings.ContainerCapacityConstructorsis enabled); - any type derived from
Stack<T>orQueue<T>orBlockingCollection<T>that has a constructor with zero arguments (or one constructor with one integer argument of typeintandMappaSettings.ContainerCapacityConstructorsis enabled); - the following interfaces:
IEnumerable<T>,ICollection<T>,IReadOnlyCollection<T>,ISet<T>,IList<T>,IReadOnlyList<T>,IReadOnlySet<T>,IImmutableSet<T>,IImmutableList<T>,IImmutableQueue<T>,IImmutableStack<T>,IProducerConsumerCollection<T>; - the following classes: arrays,
List<T>,ReadOnlyCollection<T>,Span<T>,ReadOnlySpan<T>,Memory<T>,ReadOnlyMemory<T>,Stack<T>,Queue<T>,ReadOnlySet<T>,HashSet<T>,SortedSet<T>,FrozenSet<T>,ImmutableHashSet<T>,ImmutableSortedSet<T>,ImmutableArray<T>,ImmutableList<T>,ImmutableQueue<T>,ImmutableStack<T>,ConcurrentBag<T>,ConcurrentQueue<T>,ConcurrentStack<T>;
- any type implementing
- What:
- A
forloop orforeachloop is added to the code; - In the loop, each element from the source collection is mapped in an element of the target collection and then added to the target collection;
- A
- Notes:
- When possible for some types (e.g.
List<T>) the usage of the constructor accepting capacity is preferred to reduce the number of allocations; - Explicit interface implementation is supported;
- Type with an empty constructor are supported if they are derived from any of the supported interfaces or classes;
- When possible for some types (e.g.
- When:
- <u>Tuples strategy</u>:
- When:
TSourceandTTargetare both tuple types,- The number of the elements in the tuple is the same,
- For each element of the tuple there exists a mapping from source element to target element;
- What:
- Each element of the source tuple is mapped into a new element of the target tuple;
- The target tuple is created by combining the elements mapped;
- Notes:
- Both named and un-named tuples are supported
- The type
Tuple<T>(and its variations with more elements) are supported;
- When:
- <u>Guid strategy</u>:
- When:
TSourceisGuidandTTargetisbyte[]orSpan<byte>orReadOnlySpan<byte>orMemory<byte>orReadOnlyMemory<byte>, ORTSourceisbyte[]orSpan<byte>orReadOnlySpan<byte>orMemory<byte>orReadOnlyMemory<byte>andTTargetisGuid;
- When:
- What:
- A mapping from
Guidtobyte[]/Span<byte>is defined using the relevantGuidconstructors or theGuid.ToByteArray()method
- A mapping from
- <u>Constructor strategy</u>:
- When:
TTargettype has one constructor with no parameters and each property with a setter can be assigned from aTSourceproperty with the same name (case-sensitive by default, configurable viaForceCaseInsensitivePropertyMapandIgnoreUnderscoreForPropertyMapinMappaSettings) OR,TTargettype has one constructor with parameters and each constructor argument can be assigned from aTSourceproperty with the same name (case-insensitive by default, with optional underscore-insensitive matching viaIgnoreUnderscoreForPropertyMapinMappaSettings);
- What:
- Each property or constructor argument is mapped and a new instance of
TTargetis generated; - Get-only dictionary or collection properties for which a mapper exists are filled with mapped values from the corresponding source;
- Each property or constructor argument is mapped and a new instance of
- Notes:
- Explicit interface implementation is supported for get-only dictionary and collection properties;
- Get-only
Stack<T>,Queue<T>,ConcurrentStack<T>,ConcurrentQueue<T>,ConcurrentBag<T>, andBlockingCollection<T>properties are filled post-construction usingPush,Enqueue, orAddrespectively; - Multiple Mappa attributes can change the behaviour of the mapping;
- When:
Currently unsupported features are:
- Generic type parameters on map methods (for example,
TTarget Map<TSource, TTarget>(TSource input)).
Other relevant packages:
- Mappa: attributes and
MappaContextused to drive the source generator; - Mappa Protobuf: methods to map
Google.Protobuf.WellKnownTypesobjects from Google.Protobuf package into common objects. - Mappa Protobuf dependency: utility methods to register the Protobuf mapper.
- Mappa Bson: methods to map
MongoDB.Bsonobjects from MongoDB.Bson package into common objects. - Mappa Bson dependency: utility methods to register the Bson mapper.
You can find samples here. Visit the Mappa documentation to learn more.
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.