Reputation: 9013
I have the following model:
public class Device
{
public string DeviceId { get; set; }
public string DeviceName { get; set; }
private ICollection<TagDevice> _tagDevices;
public virtual ICollection<TagDevice> TagDevices { get => _tagDevices ?? (_tagDevices = new List<TagDevice>()); protected set => _tagDevices = value; }
}
public class Tag : BaseEntity
{
public string Name { get; set; }
private ICollection<TagDevice> _tagDevices;
public virtual ICollection<TagDevice> TagDevices { get => _tagDevices ?? (_tagDevices = new List<TagDevice>()); protected set => _tagDevices = value; }
}
public class TagDevice
{
public int TagId { get; set; }
public string DeviceId { get; set; }
public virtual Tag Tag { get; set; }
public virtual Device Device { get; set; }
}
I have DTO class:
public class TagDisplayDto
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
public int TimesUsed { get; set; }
public int CarrierId { get; set; }
}
public class DeviceDisplayDto
{
public string DeviceId { get; set; }
public string DeviceName { get; set; }
public List<TagDisplayDto> Tags { get; set; }
}
now, I want to create mapping for DeviceDisplayDto with Tags filled:
CreateMap<Device, DeviceDisplayDto>()
.ForMember(d => d.Tags, opt => opt.MapFrom(s => s.TagDevices...))
;
TagDevices
is collection and not a Tag type, each element of collection has property with Tag type. How to create it?
Upvotes: 0
Views: 137
Reputation: 3354
You can use Select()
on collection of TagDevice
s to transform it into list of TagDisplayDto
s:
CreateMap<Device, DeviceDisplayDto>()
.ForMember(deviceDisplayDto => deviceDisplayDto.Tags, options =>
options.MapFrom(device => device.TagDevices.Select(tagDevice => new TagDisplayDto
{
CarrierId = 123, // TODO
CreatedAt = DateTime.UtcNow, // TODO
Id = tagDevice.TagId,
Name = tagDevice.Tag.Name,
TimesUsed = 0, // TODO
UpdatedAt = DateTime.UtcNow, // TODO
}).ToList()));
I marked some properties as TODO since I don't know the whole model you are using and some properties are missing. You'll need to fill it out on your own. At least that code should get you started.
As Lucian suggested, even better solution is to fully use AutoMapper functionality. Create mappings between two models:
Device
to DeviceDisplayDto
TagDevice
to TagDisplayDto
CreateMap<Device, DeviceDisplayDto>()
.ForMember(deviceDisplayDto => deviceDisplayDto.Tags, options =>
options.MapFrom(device => device.TagDevices));
CreateMap<TagDevice, TagDisplayDto>()
.ForMember(tagDisplayDto => tagDisplayDto.CarrierId, options =>
options.MapFrom(tagDevice => 123)) // TODO
.ForMember(tagDisplayDto => tagDisplayDto.CreatedAt, options =>
options.MapFrom(tagDevice => DateTime.UtcNow.AddDays(-60))) // TODO
.ForMember(tagDisplayDto => tagDisplayDto.Id, options =>
options.MapFrom(tagDevice => tagDevice.TagId))
.ForMember(tagDisplayDto => tagDisplayDto.Name, options =>
options.MapFrom(tagDevice => tagDevice.Tag.Name))
.ForMember(tagDisplayDto => tagDisplayDto.TimesUsed, options =>
options.MapFrom(tagDevice => 0)) // TODO
.ForMember(tagDisplayDto => tagDisplayDto.UpdatedAt, options =>
options.MapFrom(tagDevice => DateTime.UtcNow)); // TODO
That way, mapping logic defined above is reusable. Similarly to my first solution, you'd have to fill out properties marked with TODO
on your own.
Upvotes: 1