Reusing Mapping Configurations
Mapperly supports reusing mapping configurations across different mapping methods using the
IncludeMappingConfigurationAttribute. This enables you to share and modularize mapping logic for consistent
behavior across multiple methods.
Defining and reusing mapping configurations
Including an existing mapping configuration
To include an existing mapping configuration in another mapping method, use the IncludeMappingConfigurationAttribute
and provide the method name:
[MapProperty("Weight", "WeightInGrams")]
public partial static void CopyApple(AppleDto dto, Apple apple);
[IncludeMappingConfiguration(nameof(CopyApple))]
public partial static AppleDto ToApple(Apple apple);
Or use the provided mapping name:
[NamedMapping("CustomToApple")]
[MapProperty("Weight", "WeightInGrams")]
public partial static void CopyApple(AppleDto dto, Apple apple);
[IncludeMappingConfiguration("CustomToApple")]
public partial static AppleDto ToApple(Apple apple);
The following configurations will be included:
MapPropertyMapPropertyFromSourceMapperIgnoreTargetMapperIgnoreSourceMapperIgnoreObsoleteMembersMapperRequiredMappingMapValueMapDerivedType
Including a mapping configuration from a base class
This attribute also supports including configurations from a base class. For example, suppose you want to map
Apple to AppleDto and the mapping logic is defined for the base classes Fruit to FruitDto.
Here's how to set it up:
- Mapper
- Classes
[Mapper]
public partial class MyMapper
{
[MapProperty(nameof(Fruit.Name), nameof(FruitDto.Title))]
[MapperIgnoreSource(nameof(Fruit.PricePerUnit))]
private partial FruitDto ToFruit(Fruit fruit);
[IncludeMappingConfiguration(nameof(ToFruit))]
public partial static AppleDto Map(Apple apple);
}
class Fruit
{
public string Name { get; set; }
public decimal PricePerUnit { get; set; }
}
class FruitDto
{
public string Title { get; set; }
}
class Apple : Fruit
{
public int Weight { get; set; }
}
class AppleDto : FruitDto
{
public int Weight { get; set; }
}
Including external configurations
If the configuration is in another class, it is possible to reference it using the "fullnameof" syntax.
To do this, prefix the path with @ in the constructor argument.
It is also possible to reference it using the field or property name.
Additionally, you can also use a string reference of the method. In this case, the type must be fully qualified.
- Qualified through type
- Qualified through field/property
- Qualified through string path
using OtherNamespace;
namespace MyNamespace;
[Mapper]
public partial class FruitMapper
{
[IncludeMappingConfiguration(nameof(@OtherMapper.CopyApple))]
public partial static AppleDto ToApple(Apple apple);
}
namespace OtherNamespace;
public static class OtherMapper
{
// Property mapping configurations
public partial static void CopyApple(AppleDto dto, Apple apple);
}
[Mapper]
public partial class FruitMapper
{
private readonly OtherMapper _otherMapper = new();
[IncludeMappingConfiguration(nameof(@_otherMapper.CopyApple))]
public partial AppleDto ToApple(Apple apple);
}
public class OtherMapper
{
// Property mapping configurations
public partial void CopyApple(AppleDto dto, Apple apple);
}
using OtherNamespace;
namespace MyNamespace;
[Mapper]
public partial class FruitMapper
{
[IncludeMappingConfiguration("OtherNamespace.OtherMapper.CopyApple")]
public partial static AppleDto ToApple(Apple apple);
}
namespace OtherNamespace;
public static class OtherMapper
{
// Property mapping configurations
public partial static void CopyApple(AppleDto dto, Apple apple);
}
Restrictions
- The attribute only reuses a mapping if the mapped types are the same or a base type of the mapped type.
- If the attribute includes configurations that cause a collision, it is reported as an error.
Diagnostics
If an IncludeMappingConfigurationAttribute refers to an ambiguous mapping configuration (e.g., multiple
configurations exist with the same name), the mapper emits RMG062 to help you resolve the ambiguity.
This can be easily resolved by providing a custom name for the target mapping with NamedMapping attribute.