⚠ Deprecated: Legacy
Reserving a better name and releasing version 1
Suggested alternative: Mapster.ExtensionMethods
Creates extension methods instead of needing to expliclty call Adapt or Map
$ dotnet add package Mapster.ExtensionMethods.GeneratorMapster is a library for mapping objects from one shape to another. This library is a simple wrapper that creates extension methods on the source object with fluent-like syntax instead of needing to write .Adapt<Type>() (or mapper.Map() if using dependency injection). For example, chicken.ToTendersDto().
The extension methods are source generated and are used by tagging your implementations of IRegister with the attribute [MapsterExtensionMethod] an example register might look like this:
using Teaparty.Models;
using Mapster;
namespace Teaparty.Registers;
public class TeacupRegister : IRegister // Standard register import from mapster
{
[MapsterExtensionMethod] // The attribute you will add to generate extension methods
public void Register(TypeAdapterConfig config)
{
config.NewConfig<Teacup, TeacupDto>()
.Map(dest => dest.Material,
src => src.Materal.MaterialValue());
config.NewConfig<Teacup, TeacupRecord>()
.Map(dest => dest.Material, src => (int)src.Materal);
config.NewConfig<TeacupDto, Teacup>()
.Map(dest => dest.Materal, src => FromMaterialString(src.Material));
config.NewConfig<TeacupRecord, Teacup>()
.Map(dest => dest.Materal, src => (Material)src.Material);
}
private static Material FromMaterialString(string material) => material switch
{
"UraniumGlass" => Material.UraniumGlass,
"Ceramic" => Material.Ceramic,
"Glass" => Material.Glass,
_ => throw new NotSupportedException()
};
}
Because this is all done via code generation once you add the attribute you should be able to immediately use the extension methods in your code take a look at this demo
using Mapster;
using Mapster.ExtensionMethods;
using Mapster.ExtensionMethods.ConsoleApp.Domain;
using Mapster.ExtensionMethods.ConsoleApp.Dtos;
using Mapster.ExtensionMethods.ConsoleApp.Records;
using Mapster.ExtensionMethods.ConsoleApp.Registers;
using Mapster.ExtensionMethods.Mappers;
TypeAdapterConfig.GlobalSettings.Scan(typeof(TeacupRegister).Assembly);
Teacup recordDomain = new() { Materal = Material.UraniumGlass, Volume = 200 };
Console.WriteLine(recordDomain); //Teacup { Volume = 200, Materal = UraniumGlass }
// Using standard adapt syntax
var dto = recordDomain.Adapt<TeacupDto>();
var dbo = recordDomain.Adapt<TeacupRecord>();
Console.WriteLine($"Dto object type {dto}, volume: {dto.Volume} type {dto.Volume.GetType().FullName}. Material: {dto.Material} type {dto.Material.GetType().FullName}");
// Dto object type Mapster.ExtensionMethods.ConsoleApp.Dtos.TeacupDto, volume: 200 type System.Double. Material: UraniumGlass type System.String
Console.WriteLine($"Dbo object type {dbo}, volume: {dbo.Volume} type {dbo.Volume.GetType().FullName}. Material: {dbo.Material} type {dbo.Material.GetType().FullName}");
// Dbo object type Mapster.ExtensionMethods.ConsoleApp.Records.TeacupRecord, volume: 200 type System.Decimal. Material: 2 type System.Int32
var sourceGenDto = recordDomain.ToTeacupDto(); // Generated extension method
Console.WriteLine($"Source Gen Dto object type {sourceGenDto}, volume: {sourceGenDto.Volume} type {sourceGenDto.Volume.GetType().FullName}. Material: {sourceGenDto.Material} type {sourceGenDto.Material.GetType().FullName}");
// Dto object type Mapster.ExtensionMethods.ConsoleApp.Dtos.TeacupDto, volume: 200 type System.Double. Material: UraniumGlass type System.String
var sourceGenDbo = recordDomain.ToTeacupRecord();
Console.WriteLine($"Source Gen Dbo object type {sourceGenDbo}, volume: {sourceGenDbo.Volume} type {sourceGenDbo.Volume.GetType().FullName}. Material: {sourceGenDbo.Material} type {sourceGenDbo.Material.GetType().FullName}");
// Dbo object type Mapster.ExtensionMethods.ConsoleApp.Records.TeacupRecord, volume: 200 type System.Decimal. Material: 2 type System.Int32
If you use these generated extension methods you can use intellisense in your ide to immediately know what valid conversions are available for your domain objects, Mapster does a best attempt when using Adapt<>() which might not be desirable or confusing for new developers coming into your project.
Furthermore the generated xmldocs on the comments always have a link to the register that was used to generate the extension method so you can navigate easily to your registers.