As they say: “Hindsight is 20/20”
After publishing that blog post yesterday, and starting to layout the entire series, I realized I did everything wrong (boy, how often can I say that? ). My next series in my posts relies on the audience knowing and understanding AutoMapper. And, not even the simplest of parts of AutoMapper, it uses more of the intermediate functionality.
So, with that being said, I wanted to jump in-line here real quick and cover AutoMapper.
If you were like me a year ago, I looked at AutoMapper and thought, “Meh.” Great, a framework to map objects into other objects. Yay.
But, I didn’t get it at the time. It hadn’t clicked.
In the MVC world, one of the best practices out there (and there are many, I’m only advocating one; make your own opinion here) is that you have POCO (Plain Old CLR Object) – this is just a very basic class that has properties, and no logic. What I used to call a “Wrapper”; a dummy object that I would shove data into and pass around. Many times you need to transform the data in that POCO to another object, say a Model (if you’re using MVC) to pass to the View. This is where AutoMapper comes into play. Now, granted, there are many different architectures, opinions, ways to do thing.
So, let’s get started.
Automatic Property Mapping
First, we’re going to go over the most basic scenario of AutoMapper: automapping. This is where AutoMapper will try to resolve the mapping itself, looking for like-named properties in the source and destination objects.
Let’s setup the two classes we want to map back and forth: keeping with my theme from my earlier post, I’m going to use a User class and a Contact class. They should share some data, but ultimately Contact will have some fields on it’s own.
Here they are:
Nothing to them. A few shared properties, but some unique ones.
Now, check out this magic on how we map one to the other:
In that first line, I call Mapper.CreateMap, passing in the source object, and the destination object. In more complex scenarios this won’t work, but this is the most simplest use of AutoMapper – it will create a map for like-named properties. Note: You’ll want to add this call wherever your app starts up. If it’s a web app, stick it in Application_Start in your global.asax.
From there, I new up User and fill it with data. I then call Mapper.Map, telling it the source and destination again in the type parameters, and passing in my User object. It returns me a ContactModel class with data mapped where possible.
Finally, I print out myContact.FirstName which is, you guessed it… “Jason”. Easy!
Manual Column-level Mapping
But, what about that other data we want to carry over? Some of that data should go to Contact, but AutoMapper just doesn’t know what to do with it. Here’s how you can tell AutoMapper how to handle a specific mapping (it’ll still do the automapping where it can):
I simply added a .ForMember() call on the CreateMap() call. You can follow along the syntax there, too, and see I’m telling it that for Contact.FullName, concatenate User.FirstName and User.LastName with a space in between.
Custom Type Converters
However, sometimes those ForMember() mapping calls just won’t do. There’s implied inference with the mapper, still, that it does a little black magic to reflect and assign values over. If you need to get down and dirty and do the conversions yourself, you have to get into type converters.
Type converters allow you to hook directly into the mapping process, and handle the entire mapping yourself. Sounds complicated, but it’s easy. First, let’s build our ITypeConverter:
As you can see, this is a class that implements ITypeConverter, and declares the source and destination mapping in the interface declaration.
From there, you implement a Convert() method, passing the source type document, returning a destination type object. And, whatever you do in between is up to you.
In my case, I do my mapping logic of building FullName, mapping over FirstName and LastName, and putting the EmailAddress into the BusinessEmailAddress property. Then, I return it. But, you can see that this is where you would do any of your needed logic around scrubbing, converting, etc…
Now, to plug this in. It’s super simple, like so:
As you can see, all we did was replace our ForMember() calls above with a final method call to ConvertUsing(), passing in our new converter as the type.
That’s easy! And, that’s AutoMapper 101.
There’s so much more that AutoMapper does. I recommend you check out http://automapper.codeplex.com/ to see everything it does. It’s pretty amazing stuff overall, and I think you’ll find it will become a major component in your next solution.