Mapster - how to map to multiple entities

380 views Asked by At

Using Mapster Mapper I feel repeating code that should not be necessary.

public class Workshop
{
    public Guid Id {get;set;}
    public string? Title {get;set;}
    public string? Text {get;set;}

    public IList<WorkshopParticipant> WorkshopParticipants {get;set;}
}

public class WorkshopDto
{
    public Guid Id {get;set;}
    public string? Title {get;set;}
    public int Participants {get;set;}
}

public class WorkshopWithTextDto : WorkshopDto
{
    public string? Text {get;set;}
}

TypeAdapterConfig<Workshop, WorkshopDto>.NewConfig()
  .Map(dest => dest.Participants, src => src.Participants!.Count(x => x.Status == "attended")))

// Why should I have this, when WorkshopWithTextDto is inheriting from WorkshopDto that already have the mapping?
TypeAdapterConfig<Workshop, WorkshopWithTextDto>.NewConfig()
  .Map(dest => dest.Participants, src => src.Participants!.Count(x => x.Status == "attended")))

Is there any way I can reuse the mapping, so that I don't have to repeat the participant counting?

From other SO-questions I see that it's possible to use a tuple on the source object, but it doesn't seem to be possible on the destination - or am I wrong?

The participant-counting example is just to describe the problem. Often it's far more complex calculations, that would be nice to only have to maintain one place.

One solution is to have a function that assigns a value to the destination, like:

public static int CountParticipants(IList<WorkshopParticipant> workshopParticipants)
{
    return workshopParticipants!.Count(x => x.Status == "attended");
}

TypeAdapterConfig<Workshop, WorkshopDto>.NewConfig()
  .Map(dest => dest.Participants, src => CountParticipants(src.WorkshopParticipants!))

TypeAdapterConfig<Workshop, WorkshopWithTextDto>.NewConfig()
  .Map(dest => dest.Participants, src => CountParticipants(src.WorkshopParticipants!))

But I would still have to do two TypeAdapterConfigs.

Can this be done "smarter" - more easy to maintain?

1

There are 1 answers

1
jarmanso7 On BEST ANSWER

See my comment under your question. Also, according to Mapster documentation, you can include derived type to the based type declaration so it copies its settings:

TypeAdapterConfig<Vehicle, VehicleDto>.NewConfig()
    .Include<Car, CarDto>();

Vehicle vehicle = new Car { Id = 1, Name = "Car", Make = "Toyota" };
var dto = vehicle.Adapt<Vehicle, VehicleDto>();

dto.ShouldBeOfType<CarDto>();
((CarDto)dto).Make.ShouldBe("Toyota"); //The 'Make' property doesn't exist in Vehicle