Thursday, March 24, 2011

Auto Mapper

One of the most repeaterseted tasks of programming against a 3-tier design is the need to convert objects at each layer.

Persistence Layer → Business Logic Layer → Presentation Layer
Entities → Domain Objects → (Model - View Model)

In a typical Microsoft technologies based design techniques the Entities → Domain Objects transformation can be automated by an ORM technique like NHibernate.

This leaves us with the tedious manual conversion of Domain Objects to View Models. While the Domain Object design is driven by how we envision the business domain, the view models are generally govern by the User Interface. Pretty much all the time there’s a gap between the two class structures. This is where a tool like AutoMapper comes in handy.

With AutoMapper you can pre-create maps (mappings properties of destination class to source class) between two classes and then when a conversion is needed just pass the source object and the mapping to the AuroMapper to receive the resultant object. This technique has couple of advantages.
1. All the transformation logic is central. Maintenance of the transformation with time (when domain objects evolve) is easy and error free since you know you have to change it in only 1 place.
2. The transformation code it self is terse as AutoMapper abstracts most conversions.

Examples - Creating Maps:
1. Destination is a flat object with matching property names.


Mapper.CreateMap<SourceObject, DestObject>(); 


2. Same kind of transformation but for a list of items


Mapper.CreateMap<List<SourceObject>, List<DestObject>>();


3. Destination object structure is not totally aligned with the source
Source


Class Student {
string FirstName;
string LastName;
DateTime BirthDate;
}


Destination


Class StudentModel {
string FullName;
string BirthYear;
}

Mapping


Mapper.CreateMap<>()
.ForMember(dest=> dest.FullName, opt => opt.MapFrom(src=> src.FirstName + src.LastName))
.ForMember(dest=> dest.BirthYear, opt=> opt.MapFrom(src=> src.BirthDate.Year)

4. Polymorphic Mapping.
Sources


Class ParentSource {
string parentValue;
}
Class ChildSource {
string childValue;
}

Destinations


Class ParentDest {
string parentDest;
}

Class ChildDest {
string childDest;
}

Creating the map (IncludeMap clause)


Mapper.CreateMap<ParentSource, ParentChild>().Include<ChildSource, ChildDest>();
Mapper.CreateMap<ChildSource,ChildDest>();

It's also important to be sure that your mappings do not break over time. One way to keep firm track of them is to have a unit test verifying all your mappings. This can be done using the 

public void AutoMapperTest()
{
      AutoMapperConfiguration.Configure();
      Mapper.AssertConfigurationIsValid();
}

UPDATE (4th April 2014)

An excellent discussion on AutoMapper where the creator jboggard also pitches in;
http://www.uglybugger.org/software/post/friends_dont_let_friends_use_automapper
Post a Comment