Search code examples
c#automapperautomapper-5

Automapper - map property to collection


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?


Solution

  • 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;
        }