Reputation: 113
I have a question regarding Automapper, I have an flat list of objects that i must return in transformed DTO object to frontend, let's say, List of
List<Cars> list =
Cars
{
public string PartCode { get; set; }
public bool Enabled { get; set; }
public string CarCode { get; set; }
public int CarId { get; set; }
public int PartId { get; set; }
}
and i need to map it to object:
public class CarsDTO
{
public int CarId;
public string CarCode;
public List<PartsDTO> CarParts;
}
public class PartDTO
{
public Part Id;
public string PartCode;
public bool Enabled;
}
And example data:
part_id part_code car_id car_code enabled
1 WINDOW 1 MUSTANG true
2 WHEELS 1 MUSTANG true
3 BUMPER 2 MONDEO true
4 HOOD 2 MONDEO false
5 WINDSHIELD 2 MONDEO true
6 TIRE 3 KA true
7 STEERING_WHEEL 4 FOCUS false
8 TRANSMISSION 4 FOCUS true
And proposed output after mapping in json:
"parts": [
{
"carId": 1,
"carCode": "MUSTANG",
"carParts": [
{
"id": 1,
"partCode": "WINDOW",
"enabled": true
},
{
"id": 2,
"partCode": "WHEELS",
"enabled": true
}
]
},
{
"carId": 2,
"carCode": "MONDEO",
"carParts": [
{
"id": 3,
"partCode": "BUMPER",
"enabled": true
},
{
"id": 4,
"partCode": "HOOD",
"enabled": false
},
{
"id": 5,
"partCode": "WINDSHIELD",
"enabled": true
}
]
},
{
"carId": 3,
"carCode": "KA",
"carParts": [
{
"id": 6,
"partCode": "TIRE",
"enabled": true
},
]
},
{
"carId": 4,
"carCode": "FOCUS",
"carParts": [
{
"id": 7,
"partCode": "STEERING_WHEEL",
"enabled": false
},
{
"id": 8,
"partCode": "TRANSMISSION",
"enabled": true
]
}
]
Ive managed to map object in Linq with following query:
List<CarParts> carParts = new List<CarParts>();
List<CarPartsList> list = (from t in carParts
group t by new { t.CarCode, t.CarId }
into grp
select new CarPartsList()
{
GroupCode = grp.Key.CarCode,
GroupId = grp.Key.CarId,
GroupRights = (from
carPart in carParts
where userRight.CarCode == grp.Key.CarCode
select new Part { Id = carPart.PartId, PartCode = carPart.Code, Enabled = carPart.Enabled }).ToList()
}).ToList();
But the project im working on requires Automapper to transform DTO objects, and I dont know the solution:/ Ive read the docs at: https://docs.automapper.org/en/stable/Nested-mappings.html But the example in docs is so simple that i cant make use of it.
Upvotes: 1
Views: 1231
Reputation: 4219
The best answer here would be to not use AutoMapper, since in this case it will just introduce unnecessary complexity instead of simplifying your code. The usage guidelines even state:
DO NOT use AutoMapper except in cases where the destination type is a flattened subset of properties of the source type
However...
If your project requires using AutoMapper here, one way would be to define a Custom Type Converter that essentially does the same LINQ projection that you would have done otherwise:
public class CarPartConverter : ITypeConverter<IEnumerable<Cars>, IEnumerable<CarsDTO>>
{
public IEnumerable<CarsDTO> Convert(IEnumerable<Cars> source, IEnumerable<CarsDTO> destination, ResolutionContext context)
{
return source
.GroupBy(c => new {c.CarCode, c.CarId})
.Select(g => new CarsDTO
{
CarCode = g.Key.CarCode,
CarId = g.Key.CarId,
CarParts = g.Select(v => new PartsDTO
{
Id = v.PartId,
PartCode = v.PartCode,
Enabled = v.Enabled
}).ToList()
});
}
}
Here's a complete example using that converter:
static void Main(string[] args)
{
IMapper mapper = new MapperConfiguration(cfg => {
cfg.CreateMap<IEnumerable<Cars>, IEnumerable<CarsDTO>>().ConvertUsing<CarPartConverter>();
}).CreateMapper();
List<Cars> cars = new List<Cars>
{
new Cars {PartId = 1, PartCode = "WINDOW", CarId = 1, CarCode = "MUSTANG", Enabled = true},
new Cars {PartId = 2, PartCode = "WHEELS", CarId = 1, CarCode = "MUSTANG", Enabled = true},
new Cars {PartId = 3, PartCode = "BUMPER", CarId = 2, CarCode = "MONDEO", Enabled = true}
};
IEnumerable<CarsDTO> dtos = mapper.Map<IEnumerable<CarsDTO>>(cars);
Console.WriteLine(JsonConvert.SerializeObject(dtos, Formatting.Indented));
Console.ReadLine();
}
Which gives the following results:
Upvotes: 3