Bill
Bill

Reputation: 266

Automapper: Best practices for ReverseMap

I'm looking for some guidance on the usage of ReverseMap in configuring the mappings for Automapper.

I'm using Automapper to map between my DB Entities and my Models. For clarity, here is simplified example of what they look like:

public class Document
{
    public string Id { get; set; }
    public List<Element> Elements { get; set; }
}

public class Element
{       
    public string Name { get; set; }       
        public virtual ElementType Type { get; set; }
}

public class ElementText : Element
{      
        public string Value { get; set; }      
        public Hashtable Attributes { get; set; }      
        public override ElementType Type { get; set; }
}


public class DocumentModel
{
        public string Id { get; set; }
        public List<ElementModel> Elements { get; set; }    
}

public class ElementModel
{       
    public string Name { get; set; }       
    public virtual ElementType Type { get; }
}

public class ElementTextModel : ElementModel
{
        public string Value { get; set; }
        public Hashtable Attributes { get; set; }
        public override ElementType Type { get { return ElementType.TEXT; } }
}

So the Document classes are the primary classes and stores lists of Elements and derived classes from Element like ElementText in the Elements list.

Mapping profile:

 public MappingProfile()
        {

            this.CreateMap<Document, DocumentModel>().ReverseMap();
            this.CreateMap<Element, ElementModel>().ReverseMap();
            this.CreateMap<ElementText, ElementTextModel>().ReverseMap();
        }

Now this profile works in most cases, but fails to map the derived classes within the list. It maps them to the base class instead. (So ElementText members become Element, etc)

I can fix that by using IncludeAllDerived in the profile like so:

 public MappingProfile()
        {

            this.CreateMap<Document, DocumentModel>().ReverseMap();
            this.CreateMap<Element, ElementModel>()
                 .IncludeAllDerived()
                 .ReverseMap();

            this.CreateMap<ElementText, ElementTextModel>().ReverseMap();
        }

But it appears that the order of .IncludeAllDerived() and .ReverseMap() matter. And the only way to get derived classes working in both direction is to use:

 public MappingProfile()
        {

            this.CreateMap<Document, DocumentModel>().ReverseMap();
            this.CreateMap<Element, ElementModel>()
                 .IncludeAllDerived()
                 .ReverseMap().IncludeAllDerived();

            this.CreateMap<ElementText, ElementTextModel>().ReverseMap();
        }

Which starts to get a little clunky for my taste. I'd rather ditch ReverseMap and explicitly define the mapping for both directions.

 public MappingProfile()
        {

            this.CreateMap<Document, DocumentModel>().ReverseMap();
            this.CreateMap<Element, ElementModel>()
                 .IncludeAllDerived()
            this.CreateMap<ElementModel, Element>()
                 .IncludeAllDerived();

            this.CreateMap<ElementText, ElementTextModel>().ReverseMap();
        }

So my question is, when should I use ReverseMap? Never? Only in very simple cases?

Does explicitly specifying the mapping in both directions give the same result? The documentation is a little unclear except in a usage guidelines post here Jimmy says:

X AVOID ReverseMap in cases except when mapping only top-level, non-flattened properties

Reverse mapping can get very complicated very quickly, and unless it's very simple, you can have business logic showing up in mapping configuration.

Upvotes: 0

Views: 2910

Answers (0)

Related Questions