74

I have the case where I want to map an entity to a viewmodel and back. I have to specify the mapping explicitly with ForMember() because their properties do not share the exact same names. Here is a short example of how my classes look like:

public class PartTwo {
    public int Integer { get; set; }
}

public class PartTwoViewModel {
    public int PartInteger { get; set; }
}

And I want to use them this way:

Mapper.CreateMap<PartTwo, PartTwoViewModel>()
    .ForMember(dst => dst.PartInteger, opt => opt.MapFrom(src => src.Integer))
    .ReverseMap();

var partTwoViewModel = new PartTwoViewModel() { PartInteger = 42 };
var partTwo = Mapper.Map<PartTwoViewModel, PartTwo>(partTwoViewModel);
Assert.AreEqual(partTwoViewModel.PartInteger, partTwo.Integer);

But it does not match the property PartInteger to Integer. (Integer is 0.)

Is there a way to make this work? (When the properties of both classes have the same names it works.) Do I have to set some kind of option in the method ForMember()?

Boiethios
  • 38,438
  • 19
  • 134
  • 183
toni
  • 2,270
  • 3
  • 22
  • 27

2 Answers2

164

ReverseMap returns an IMappingExpression that represents the reversal of the mapping. Once you call, it subsequent calls will be for configuring the reversal of the map.

Here's an example:

Mapper.CreateMap<CartItemDto, CartItemModel>()
      .ForMember(dest => dest.ExtendedCost, opt => opt.Ignore())
      .ReverseMap()
          .ForMember(dest => dest.Pricing, opt => opt.Ignore())

This will ignore the Pricing field in the reverse direction.

Jon Wingfield
  • 1,875
  • 2
  • 11
  • 8
  • 1
    Excellent. While it's still inconvenient to have to create the member mappings again, this is better than having to create an entirely new map. – Cody Dec 02 '14 at 20:28
  • @jon Wingfield I appreciate your answer, but I am also a little confused. If I still have to re-do all of may .ForMember calls after I call ReverseMap, is it gaining me anything? Is it just a that .ignore is broken? – JMarsch Aug 27 '16 at 00:20
  • 1
    @JMarsch It's been a while, but I don't think you need to redo _all_ the `ForMember` calls, just anything that isn't already mapped. – Jon Wingfield Aug 27 '16 at 02:25
56

You could define your configuration like this:

Mapper.CreateMap<PartTwo, PartTwoViewModel>()
    .ForMember(dst => dst.PartInteger, opt => opt.MapFrom(src => src.Integer));

Mapper.CreateMap<PartTwoViewModel, PartTwo>()
    .ForMember(dst => dst.Integer, opt => opt.MapFrom(src => src.PartInteger));

UPDATE

Here is the commit where ReverseMap was initially implemented. From what I can see in the code, it only creates a simple reverse mapping. For example, in this case it would automatically configure the equivalent of:

Mapper.CreateMap<PartTwoViewModel, PartTwo>();

To get anything more complex, I'm afraid that you're going to have to configure it manually.

Mightymuke
  • 5,094
  • 2
  • 31
  • 42
  • 1
    Yes this works. I hoped that I would not have to define the reverse mapping, because I have many properties which I map via ForMember(). – toni Nov 21 '12 at 13:30