Trochę magii może, ale mniej kodu to mniej błędów i mniejszy "narzut kognitywny".
xD
No na pewno magiczne generowanie mapperow to "mniejszy narzut kognitywny" niż zwykły statyczny mapper własnoręcznie napisany.
Przykład z docsow mapperly.
Najpierw trzeba nasrać partiali i atrybutów:
Kopiuj
[Mapper(EnumMappingStrategy = EnumMappingStrategy.ByName)]
public static partial class CarMapper
{
[MapProperty(nameof(Car.Manufacturer), nameof(CarDto.Producer))] // Map property with a different name in the target type
public static partial CarDto MapCarToDto(Car car);
}
Który później wygeneruje taki piękny i czytelny kod "który przecież można podejrzeć":
Kopiuj
public static partial class CarMapper
{
[global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "0.0.1.0")]
public static partial global::Riok.Mapperly.Sample.CarDto MapCarToDto(global::Riok.Mapperly.Sample.Car car)
{
var target = new global::Riok.Mapperly.Sample.CarDto();
target.Name = car.Name;
target.NumberOfSeats = car.NumberOfSeats;
target.Color = MapToCarColorDto(car.Color);
if (car.Manufacturer != null)
{
target.Producer = MapToProducerDto(car.Manufacturer);
}
else
{
target.Producer = null;
}
target.Tires = MapToListOfTireDto(car.Tires);
return target;
}
[global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "0.0.1.0")]
private static global::Riok.Mapperly.Sample.CarColorDto MapToCarColorDto(global::Riok.Mapperly.Sample.CarColor source)
{
return source switch
{
global::Riok.Mapperly.Sample.CarColor.Black => global::Riok.Mapperly.Sample.CarColorDto.Black,
global::Riok.Mapperly.Sample.CarColor.Blue => global::Riok.Mapperly.Sample.CarColorDto.Blue,
_ => throw new global::System.ArgumentOutOfRangeException(nameof(source), source, "The value of enum CarColor is not supported"),
};
}
[global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "0.0.1.0")]
private static global::Riok.Mapperly.Sample.ProducerDto MapToProducerDto(global::Riok.Mapperly.Sample.Manufacturer source)
{
var target = new global::Riok.Mapperly.Sample.ProducerDto(source.Id, source.Name);
return target;
}
[global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "0.0.1.0")]
private static global::Riok.Mapperly.Sample.TireDto MapToTireDto(global::Riok.Mapperly.Sample.Tire source)
{
var target = new global::Riok.Mapperly.Sample.TireDto();
target.Description = source.Description;
return target;
}
[global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "0.0.1.0")]
private static global::System.Collections.Generic.List<global::Riok.Mapperly.Sample.TireDto> MapToListOfTireDto(global::System.Collections.Generic.IReadOnlyCollection<global::Riok.Mapperly.Sample.Tire> source)
{
var target = new global::System.Collections.Generic.List<global::Riok.Mapperly.Sample.TireDto>(source.Count);
foreach (var item in source)
{
target.Add(MapToTireDto(item));
}
return target;
}
}
A prosty statyczny mapper mógłby wyglądać jakoś tak:
Kopiuj
using System;
using System.Linq;
using Riok.Mapperly.Sample;
public static class CarMapper
{
public static CarDto MapCarToDto(Car car)
{
return new CarDto
{
Name = car.Name,
NumberOfSeats = car.NumberOfSeats,
Color = car.Color switch
{
CarColor.Black => CarColorDto.Black,
CarColor.Blue => CarColorDto.Blue,
_ => throw new ArgumentOutOfRangeException(nameof(car.Color), car.Color, "The value of enum CarColor is not supported")
},
Producer = car.Manufacturer != null
? new ProducerDto(car.Manufacturer.Id, car.Manufacturer.Name)
: null,
Tires = car.Tires
.Select(t => new TireDto { Description = t.Description })
.ToList()
};
}
}
Do własnej oceny czytelników pozostawiam zdecydowanie która metoda ma mniejszy narzut kognitywny i jest łatwiejsza do utrzymania i debugowania.