Problem
All we don’t want to write mappers boilerplated code, because it is boring. So smart developers use different mappers, such as AutoMapper, Mapster and so on. However, we suppose that these libraries have to use reflection to map our POCO to DTO and we know that reflection one of the most slowest thing. Fortunately, I have good news for you, because we can just generate mappers code, so we avoid reflection.
Onion
On these to images you can see 2 situations:
- Usuall onion scheme shows that application layer can expose only DTOs, so we have IMapper abstraction on this layer and DTOs classes, which can also be generetated by Mapster (because apllcation layer knows about entites, so generator can base on them)
- If you use blazor, you can want to have shared DTOs library so all DTOs can be reused by frontend. In that case, such shared library does not know anyting about domain entities, so can’t be generated by mapster. However, we still can generate our IMappers
Let’s consider second variant.
Create project with layers
Get mapster
#skip this step if you already have dotnet-tools.json
dotnet new tool-manifest
dotnet tool install Mapster.Tool
Add mapster to Application layer
PM> Install-Package Mapster
IMapper
All we need just use data attribute [Mapper]
for our interface to tell mapster which mappers we want to generate
[Mapper]
public interface IEntityMapper
{
//map from POCO to DTO
EntityDto MapToDto(Entity entity);
}
Now, let’s add next lines to application.csproj
<Target Name="Mapster">
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet build" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet tool restore" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster model -a "$(TargetDir)$(ProjectName).dll"" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster extension -a "$(TargetDir)$(ProjectName).dll"" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster mapper -a "$(TargetDir)$(ProjectName).dll"" />
</Target>
And last one, run dotnet msbuild -t:Mapster
Result
As a result, we can see generated mappers, which we can inject to our application
Conclusion
We can use mappers as the way we use to, but avoiding reflection cost. As always source code you can find on github