I am creating an AutoMapper configuration, where the structure does not match the destination in 1:1, I have to wrap my primary and secondary contact in the ContactResponse
object. I cannot figure out how to use the mapping I created before to map the Contact
object to a CommunicationContactResponse
without redoing the config.
public class VendorResponseMappingProfile : Profile
{
public VendorResponseMappingProfile()
{
this.CreateMap<Contact, CommunicationContactResponse>()
.ForMember(dest => dest.Phone, opt => opt.MapFrom(src => src.Phone))
.ForMember(dest => dest.Email, opt => opt.MapFrom(src => src.Email));
this.CreateMap<Vendor, VendorResponse>()
.ForMember(dest => dest.id, opt => opt.MapFrom(src => src.Id))
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name))
.ForMember(dest => dest.Memo, opt => opt.MapFrom(src => src.Memo))
.ForMember(dest => dest.Active, opt => opt.MapFrom(src => src.Active))
.ForMember(dest => dest.Contact, opt => opt.MapFrom(src => new ContactResponse
{
// Here i have to redo the mapping from above are there a way to use the mapping from above instead?
PrimaryContact = src.PrimaryContact != null ? new CommunicationContactResponse
{
Phone = src.PrimaryContact.Phone,
Email = src.PrimaryContact.Email
} : null,
SecondaryContact = src.SecondaryContact != null ? new CommunicationContactResponse
{
Phone = src.SecondaryContact.Phone,
Email = src.SecondaryContact.Email
} : null
}));
}
}
You need the Custom Value Resolver to use the mapping rule that has been registered for both PrimaryContact
and SecondaryContact
fields mapping from Contact
to CommunicationContactResponse
.
While AutoMapper will automatically map the source and destination members if both have the same naming. Thus you don't need to specify the mapping rule for each member unless:
Without extra configuration, AutoMapper requires a flattened destination to match the source type’s naming structure. When you want to project source values into a destination that does not exactly match the source structure, you must specify custom member mapping definitions.
Solution 1:
public class VendorResponseMappingProfile : Profile
{
public VendorResponseMappingProfile()
{
this.CreateMap<Contact, CommunicationContactResponse>();
this.CreateMap<Vendor, VendorResponse>()
.ForMember(dest => dest.Contact, opt => opt.MapFrom((src, dest, srcMember, context) => new ContactResponse
{
PrimaryContact = context.Mapper.Map<CommunicationContactResponse>(src.PrimaryContact),
SecondaryContact = context.Mapper.Map<CommunicationContactResponse>(src.SecondaryContact)
}));
}
}
(Updated) Solution 2:
As suggested by @Lucian, a mapping from Vendor
to ContactResponse
is another option that is more simple.
public class VendorResponseMappingProfile : Profile
{
public VendorResponseMappingProfile()
{
this.CreateMap<Contact, CommunicationContactResponse>();
this.CreateMap<Vendor, VendorResponse>()
.ForMember(dest => dest.Contact, opt => opt.MapFrom(src => src));
this.CreateMap<Vendor, ContactResponse>();
}
}