3

given this mapping

_mapper.Map(personDto, person, opt => opt.ConfigureMap()
    .ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null))
);

person before mapping

FirstName: "John"
LastName: "Doe"
Email: "John.Doe@gmail.com"

personDto before mapping

FirstName: "Jim"
LastName: "Denver"
Email: NULL

expected output person

FirstName: "Jim"
LastName: "Denver"
Email: "John.Doe@gmail.com"

actual output person

FirstName: "Jim"
LastName: "Denver"
Email: NULL

mapper came from this post https://stackoverflow.com/a/43947731/3511012


Update, I also tried using ResolveUsing and it has the same output

_mapper.Map(personUpdateDto, person, opt => opt.ConfigureMap()
    .ForAllOtherMembers(opts => opts.ResolveUsing((src, dest, srcMember, dstMember) => srcMember ?? dstMember))
);

stackoverfloweth
  • 6,669
  • 5
  • 38
  • 69
  • This doesn't answer your question as it has to be configured for each member, but maybe it will help. How about use null coalescing operator in the member map configuration. `.ForMember(dest => dest.Email, opt => opt.MapFrom((src, dest) => src.Email ?? dest.Email))` – chadnt Feb 13 '19 at 20:06
  • I'm using `ForAllMembers` so it can't specifically look at `Email`. I did try an adaptation of your idea with `.ForAllMembers(opts => opts.ResolveUsing((src, dest, srcMember, dstMember) => srcMember ?? dstMember))` but that had the same effect as `Condition` – stackoverfloweth Feb 13 '19 at 20:16

1 Answers1

0

If I understand correctly then you have a predefined mapping from PersonDto to Person and trying to configure that mapping in the Map method. In that case, the code below really doesn't work as you want because the lambda in the ForAllMembers is never being called.

var config = new MapperConfiguration(cfg => cfg.CreateMap<PersonDto, Person>());//.ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null)));
var mapper = config.CreateMapper();
var person = new Person { FirstName = "John", LastName = "Snow" ,Email="test@mail.com"};
var personUpdateDto = new PersonDto { FirstName = "Jim", LastName = "Denver" };
var a = mapper.Map(personUpdateDto, person, opt => opt.ConfigureMap()
            .ForAllMembers(opts => opts.Condition((src, dest, srcMember) =>
            {
                return srcMember != null;
            }
            )));

But the code below works as you want:

var config = new MapperConfiguration(cfg => cfg.CreateMap<PersonDto, Person>().ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null)));
var mapper = config.CreateMapper();
var person = new Person { FirstName = "John", LastName = "Snow", Email = "test@mail.com" };
var personUpdateDto = new PersonDto { FirstName = "Jim", LastName = "Denver" };
var a = mapper.Map(personUpdateDto, person);

Another way to work with inline maps is to define empty mapper configuration and then add inline maps:

var config = new MapperConfiguration(cfg => { });
var mapper = config.CreateMapper();
var person = new Person { FirstName = "John", LastName = "Snow", Email = "test@mail.com" };
var personUpdateDto = new PersonDto { FirstName = "Jim", LastName = "Denver" };
var a = mapper.Map(personUpdateDto, person,opts=>opts.ConfigureMap()
.ForAllMembers(opts2 => opts2.Condition((src, dest, srcMember) =>
{
    return srcMember != null;
}
)));
Samvel Petrosov
  • 7,580
  • 2
  • 22
  • 46