Search code examples
c#.netautomappermapper

AutoMapper - Map and add elements to list conditionally


I have a unique requirement when mapping some elements using AutoMapper.

I am not finding any effective solution with built scenarios:

  1. I want to add phone number details to the contacts list if the phone number is not null.
  2. I want to add email address details to the contacts list if the email is not null.
CreateMap<UserModel, UserDefinition>()
              .ForMember(d => d.Id, o => o.Ignore()) 
              .ForMember(d => d.UserName, o => o.MapFrom(s => s.Username))
              .ForMember(d => d.Contacts, o =>  
                  new List<UserContactDefinition>()
                  {
                      o.MapFrom(s => !string.IsNullOrWhiteSpace(s.PhoneNumber) ?
                      new UserContactDefinition
                      {
                          Type = ContactType.Phone,
                          IsPrimary = true,
                          Label = s.PhoneType,
                          Value = s.PhoneNumber
                      }: null,
                      o.MapFrom(s => !string.IsNullOrWhiteSpace(s.ContactEmail) ?
                       new UserContactDefinition
                       {
                           Type = ContactType.Email,
                           IsPrimary = true,
                           Label = s.EmailType,
                           Value = s.Email
                       }: null
                  }                   
              ); 

This code is not working and I don't want to add empty elements if there is no value.

Any leads to this?


Solution

  • For your scenario, you need the Custom Value Resolver to map the destination member for the Contacts property.

    1. Implement UserContactDefinitionListResolver custom value resolver.
    public class UserContactDefinitionListResolver : IValueResolver<UserModel, UserDefinition, List<UserContactDefinition>>
    {
        public List<UserContactDefinition> Resolve(UserModel src, UserDefinition dst, List<UserContactDefinition> dstMember, ResolutionContext ctx)
        {
            dstMember = new List<UserContactDefinition>();
            
            if (!string.IsNullOrWhiteSpace(src.PhoneNumber))
                dstMember.Add(new UserContactDefinition
                {
                    Type = ContactType.Phone,
                    IsPrimary = true,
                    Label = src.PhoneType,
                    Value = src.PhoneNumber
                });
                
            if (!string.IsNullOrWhiteSpace(src.ContactEmail))
                dstMember.Add(new UserContactDefinition
                {
                    Type = ContactType.Email,
                    IsPrimary = true,
                    Label = src.EmailType,
                    Value = src.ContactEmail
                });
            
            return dstMember;
        }
    }
    
    1. Add mapping configuration/profile for the member Contacts to use the UserContactDefinitionListResolver.
    CreateMap<UserModel, UserDefinition>()
        .ForMember(d => d.Id, o => o.Ignore())
        .ForMember(d => d.UserName, o => o.MapFrom(s => s.Username))
        .ForMember(d => d.Contacts, o => o.MapFrom(new UserContactDefinitionListResolver()));
    

    Demo @ .NET Fiddle