Using AutoMapper to build base class for mappers between domain classes and models

It is often good idea to isolate our domain model from consuming applications by using service layer and data transfer objects (DTO) or application specific models. Using DTO-s means that we need two-way mapping between domain classes and DTO-s. In this posting I will show you how to use AutoMapper to build generic base class for your mappers.

AutoMapper

AutoMapper is powerful object to object mapper that is able to do also smart and complex mappings between objects. Also you can modify existing and define your own mappings. Although it is possible to write way faster lightweight mappers still AutoMapper offers very good performance considering all the nice features it provides.

What’s most important – AutoMapper is easy to use and it fits perfect to the context of this posting.

Why mapping?

To those who have no idea about the problem scope I explain a little bit why mapping between domain classes and application specific models or DTO-s is needed. Often domain classes have complex dependencies between each other and they may also have complex dependencies with their technical environment. Domain classes may have cyclical references that makes it very hard to serialize them to text based formats. And domain classes may be hard to create.

By example, if you are using vendor offered powerful grid component then this component may want to serialize its data source so it can use it on client side to provide quick sorting and filtering of grid data. Moving from server to client means serialization to JSON or XML. If our domain objects have cyclical references (and it is normal they have) then we are in trouble. We have to use something lighter and less powerful, so we use DTO-s and models.

If you go through all complexities mentioned before you will find more issues with using domain classes as models. As we have to use lightweight models we need mappings between domain classes and models.

Base mapper

Instead of writing mapper for each type-pair mappings you can avoid writing many lines of repeating code when using AutoMapper. Here is my base class for mappers.

public abstract class BaseMapper<T, U> where T : BaseEntity where U : BaseDto, new()
{
   
protected IMappingExpression<U, T> DtoToDomainMapping { get; private set
; }
   
protected IMappingExpression<T, U> DomainToDtoMapping { get; private set
; }
 
   
public
BaseMapper()
    {
        DomainToDtoMapping =
Mapper
.CreateMap<T, U>();
 
       
var mex = Mapper
.CreateMap<U, T>()
                        .ForMember(m => m.Id, m => m.Ignore());
 
       
var refProperties = from p in typeof
(T).GetProperties()
                           
where p.PropertyType.BaseType == typeof(BaseEntity
)
                           
select
p;
 
       
foreach (var prop in
refProperties)
        {
            mex.ForMember(prop.Name, m => m.Ignore());
        }
 
       
Mapper.CreateMap<PagedResult<T>, PagedResult
<U>>()
              .ForMember(m => m.Results, m => m.Ignore());
    }
 
   
public
U MapToDto(T instance)
    {
       
if (instance == null
)
           
return null
;
 
       
var dto = new
U();
 
       
Mapper
.Map(instance, dto);
 
       
return
dto;
    }
 
   
public IList<U> MapToDtoList(IList
<T> list)
    {
       
if (list == null
)
           
return new List
<U>();
 
       
var dtoList = new List
<U>();
 
       
Mapper
.Map(list, dtoList);
 
       
return
dtoList;
    }
 
   
public PagedResult<U> MapToDtoPagedResult(PagedResult
<T> pagedResult)
    {
       
if (pagedResult == null
)
           
return null
;
 
       
var dtoResult = new PagedResult
<U>();
       
Mapper
.Map(pagedResult, dtoResult);
       
Mapper
.Map(pagedResult.Results, dtoResult.Results);
 
       
return
dtoResult;
    }
 
   
public void
MapFromDto(U dto, T instance)
    {
       
Mapper.Map(dto, instance);
    }
}

It does all the dirty work and in most cases it provides all functionality I need for type-pair mapping.

In constructor I define mappings for domain class to model and model to domain class mapping. Also I define mapping for PagedResult – this is the class I use for paged results. If inheriting classes need to modify mappings then they can access protected properties.

Also notice how I play with domain base class: the code avoids situations where AutoMapper may overwrite ID-s and properties that extend domain base class. When you start using mapping then you very soon find out how bad mess AutoMapper can create if you don’t use it carefully.

Methods of mapper base:

  • MapToDto – takes domain object and returns mapped DTO.
  • MapToDtoList – takes list of domain objects and returns list of DTO-s.
  • MapToDtoPagedResult – takes paged result with domain objects and returns paged result with DTO-s.
  • MapFromDto – maps DTO properties to domain object.

If you need more mapping helpers you can upgrade my class with your own code.

Example

To give you better idea about how to extend my base class here is the example.

public class FillLevelMapper : BaseMapper<FillLevel, FillLevelDto>
{
   
public FillLevelMapper()
    {
        DomainToDtoMapping.ForMember(
            l => l.Grade, m => m.MapFrom(l => l.Grade.GradeNo)
        );
    }
}

Mapper classes extend from BaseMapper and add their specifics to mappings that base mapper doesn’t provide.

Conclusion

Mapping is also one repeating patterns in many systems. After building some mappers from zero you start recognizing parts they have in common. I was able to separate common operations of my mappers to base class using generics and AutoMapper. Mapper classes are very thin and therefore also way easier to test. AutoMapper makes a lot of dirty work for me that is otherwise time consuming to code. Of course, by all it’s power you must use AutoMapper carefully so it doesn’t do too much work.

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    5 thoughts on “Using AutoMapper to build base class for mappers between domain classes and models

    • July 31, 2012 at 4:16 pm
      Permalink

      Needs some more usage examples, like perhaps show a sample mvc controller using your mapping.

    • July 31, 2012 at 4:22 pm
      Permalink

      AutoMapping saving time is a myth!

    • September 26, 2012 at 12:58 am
      Permalink

      Great article. I’m looking at creating a version of this so that I can initialize all BaseMapper types into IoC. One thing I did notice is that DtoToDomainMapping is never set. After the line

      foreach (var prop in refProperties)
      {
      mex.ForMember(prop.Name, m => m.Ignore());
      }

      DtoToDomainMapping = mex is required to set DtoToDomainMapping

    • December 5, 2019 at 3:33 am
      Permalink

      I’m wondering, will this still work with the current version of Automapper?

    • December 5, 2019 at 5:39 am
      Permalink

      It should work with current AutoMapper too. As Mapper.Map() is deprecated and removed from AutoMapper we must use mapping profiles. It’s possible to use this class as a base class for mapping profiles. We have to extend it from Profile class then.

    Leave a Reply

    Your email address will not be published. Required fields are marked *