Automapper - map property to collection

4.9k Views Asked by At

Source classes:

public class ApplicationDriverFormVM
{
    public ApplicationDriverAddressFormVM PresentAddress { get; set; }
    public List<ApplicationDriverAddressFormVM> PreviousAddresses { get; set; }
}

public class ApplicationDriverAddressFormVM
{
    [Required]
    [StringLength(256)]
    [Display(Name = "Address")]
    public string Address { get; set; }
    [Required]
    [StringLength(256)]
    [Display(Name = "City")]
    public string City { get; set; }
    //.....
}

Destination classes:

public class ApplicationDriverDomain
{
    public List<ApplicationDriverAddressDomain> Addresses { get; set; }
}

public class ApplicationDriverAddressDomain
{
    public int Id { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    //....
    public bool IsPresentAddress { get; set; }
}

so, I want to map PresentAddress (one object) and PreviousAddresses (collection) to Addresses property (collection), where each element has IsPresentAddress property, which should be true, if it was mapped PresentAddress and false for PreviousAddresses mapped elements. I try to write such map basic rules:

        CreateMap<ViewModels.ApplicationDriverFormVM, ApplicationDriverDomain>();
        CreateMap<ViewModels.ApplicationDriverAddressFormVM, ApplicationDriverAddressDomain>();

of course, it does not work properly. How do to it?

1

There are 1 best solutions below

1
On BEST ANSWER

This can be done with the ForMember extension methods.

This is a quick and dirty way to get what you want. It makes a new combined list of ApplicationDriverAddressFormVM to map from, but if you explore the documentation, you can probably find something more graceful.

Mapper.CreateMap<ApplicationDriverFormVM, ApplicationDriverDomain>()
    .ForMember(dest => dest.Addresses, opt => opt.MapFrom(src => src.PreviousAddresses.Union(new List<ApplicationDriverAddressFormVM>() { src.PresentAddress })));

Mapper.CreateMap<ApplicationDriverAddressFormVM, ApplicationDriverAddressDomain>();

After further investigation, I found the following approach. It uses the ResolveUsing option. Again, this is rough, and only uses the first functionality I found. You should further explore the IMemberConfigurationExpression interface, and see what other options you have

        Mapper.CreateMap<ApplicationDriverFormVM, ApplicationDriverDomain>()
            .ForMember(dest => dest.Addresses, opt => opt.ResolveUsing(GetAddresses));

...

    static object GetAddresses(ApplicationDriverFormVM src)
    {
        var result = Mapper.Map<List<ApplicationDriverAddressDomain>>(src.PreviousAddresses);
        foreach(var item in result)
        {
            item.IsPresentAddress = false;
        }
        var present = Mapper.Map<ApplicationDriverAddressDomain>(src.PresentAddress);
        present.IsPresentAddress = true;
        result.Add(present);

        return result;
    }