In September, Cory Isakson and I presented AutoMapper to the Boise .NET Developer User Group (NETDUG). As promised, I have included the sample code here. AutoMapper 1.0 RC1 is available on the CodePlex site.
At my company, we have embraced convention-over-configuration throughout our applications, from our data access framework (Fluent NHibernate) to our IoC container (StructureMap) to our build scripts to our…well, you get the picture. However, we had been hitting a pain point in our application when trying to serialize our domain objects for transport across the WCF service layer. We were also seeing some issues with using domain objects directly in our MVC views. The old way would have been to write that boring left-hand/right-hand code. We all know that left-hand/right-hand code is ugly and pollutes the methods that should be doing real work with ceremonious busy work.
Well, just as we were really getting stung by these pain points, Cory and I started talking about AutoMapper. Now, for those who have no idea what AutoMapper is, check out the Getting Started page on CodePlex. If you want to check out the source, go to the Google code site. Jimmy Bogard, the AutoMapper author, describes the AutoMapper as a convention-based object-to-object mapper.
Different Means to an End
Here is the basic idea… In the past, I would write this classic chunk of code:
var meeting = _repository.GetMeetingById(meetingId); var dto = new MeetingDto(); dto.Begins = meeting.Begins; dto.End = meeting.End; dto.Attendees = meeting.Attendees; dto.AttendeesCount = meeting.Attendees.Count; //do something meaningful
With AutoMapper, I can write this instead:
var meeting = _repository.GetMeetingById(meetingId); var dto = Mapper.Map<Meeting, MeetingDto>(meeting); //do something meaningful
Herein lies the beauty of AutoMapper. When your classes align themselves conventionally, your mapping configuration can be as simple as:
This is a trivial example, but where AutoMapper shines is in the ability to map lists and nested properties by convention. Or constructing an object based on another object’s properties. All without littering a method with ceremonial code.
Using an object-to-object mapper does have its drawbacks:
- The classic left-hand/right-hand code performs faster than mapped code, although Jimmy has made great strides in increasing performance.
- When defining unconventional mappings, you will still have left-hand/right-hand code
- There will be a learning curve for you (and/or your team) if you have not had experience with convention-based frameworks or some of the .NET 3.5 features.
However, we have found these drawbacks to be trivial when compared to the benefits.
In addition to providing the convention mappings, Jimmy has provided a toolset for enhancing the mappings. Listed here are several tools we either use or find compelling.
Custom Converters: Code to convert from source type to destination type. Defined once and implicitly used for all mappings.
Custom Resolvers: Code to convert from source value to destination value. Defined once for use by any mapping, but must be explicitly used by a mapping.
Custom Formatters: Code to reformat a type for presentation. Like resolvers, formatters are defined once and explicitly used.
Before/After Map Functions: Provides the ability to run custom code before or after the mappings are performed.
Validation Assertion: Provides a method to short-circuit at runtime (or in tests) with an explanatory exception when a mapping may cause failures.
Mapping Profiles: Profile is a base class that helps you organize your code. If you are familiar with StructureMap’s Registry class, you will feel right at home with the Profile class.
Where We Use AutoMapper
We use AutoMapper to transform our object model to our presentation model. This happens in two places – in our MVC controllers and at our WCF service layer.
In the controllers, we will map from a domain model or DTO into the view model. We will also map from our view model into a message object for use by the service or domain.
At the service layer, we flatten our domain model into a DTO or map a message object to run a command against the domain.
I am including the sample code used at the NETDUG meeting. The first sample shows different ways to setup mappings (inline vs. profiles). The second sample shows some usages of custom resolvers, formatters, and before-maps.
Download the AutoMapper source. Jimmy has provided many sample classes and unit tests showing off the usage of different conventions.
Matt Hinze also posted a sample solution using AutoMapper with NerdDinner (of which I borrowed some custom formatter code – Thanks Matt!).
Download the CodeCampServer source. It is full of examples and conventions, including using an IoC/DI implementation of the AutoMapper engine.