automapper

Is it possible to use Automapper 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 can be not null at a time. I would like to map to a single destination field "NoteParent" using the logic something like bellow. 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 if 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 then do 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