Search code examples
c#automapper

AutoMapper - Is it possible to map different source fields to a destination based on condition logic?


I have a source class with multiple fields, 5 of those fields can be null but only 1 field must not be null at a time. I would like to map to a single destination field NoteParent using the logic below. i.e. I want the string in MapFrom to be put into the destination NoteParent field.

Is this possible using AutoMapper? Using the mapping below I have been able to get one of the mappings to work. Basically, only the first src value of the first record will place the value in the destination of the records that match the logic but the logic for the other possibilities does not work.

CreateMap<Note, NoteVM>()
    .ForMember(d => d.NoteParent, opt =>
    {
        opt.PreCondition(s => (s.Agent != null));
        opt.MapFrom(s => "Agent");
    })
    .ForMember(d => d.NoteParent, opt =>
    {
        opt.PreCondition(s => s.AssociatedFirm != null);
        opt.MapFrom(s => "Associated Firm");
    })
    .ForMember(d => d.NoteParent, opt =>
    {
        opt.PreCondition(s => (s.Review != null));
        opt.MapFrom(s => "Review");
    })
    .ForMember(d => d.NoteParent, opt =>
    {
        opt.PreCondition(s => s.Schedule != null);
        opt.MapFrom(s => "Schedule");
    })
    .ForMember(d => d.NoteParent, opt =>
    {
        opt.PreCondition(s => (s.Participant != null));
        opt.MapFrom(s => "Participant");
    });

Solution

  • From what I suspect, when you define multiple mapping rules with the same destination member, the behavior is the last rule overrides the previous rule(s), instead of chaining (from first to last).

    Thus, you should implement Custom Value Resolver to map multiple properties into a single property by condition.

    CreateMap<Note, NoteVM>()
        .ForMember(d => d.NoteParent, opt => opt.MapFrom((src, dest, destMember, ctx) => 
        {
            if (src.Agent != null)
                return "Agent";
    
            if (src.AssociatedFirm != null)
                return "AssociatedFirm";
    
            if (src.Review != null)
                return "Review";
    
            if (src.Schedule != null)
                return "Schedule";
    
            return "Participant";
        })
    );
    

    Demo @ .NET Fiddle