Introduction
AutoMapper is an Open Source library that provides a convention-based object-object mapper. It is a very useful tool that can help speed up your development and cut down the amount of code you need to write, particularly... object mapping code.
Overview
Object mapping is used frequently to transform input object of one type (say a Data Access Object) into an output object of a different type (say a Data Transfer Object). AutoMapper makes this transformation very simple by providing a convention-based way to transform data between these objects. So, mapping code that once looked like this:
public class ProductDAOtoProductDTOMapper
{
public ProductDTO Map(ProductDAO product)
{
return new ProductDTO
{
Name = product.Name,
Description = product.Description,
Price = product.Price,
Quantity = product.Quantity
};
}
}
...can be replaced with this:
var productDto = Mapper.Map<productdao, >(productDao);
That's it!
Getting Started with AutoMapper
All the configuration that's required to setup AutoMapper occurs in the Global.asax.cs file, within the "Application_Start
" method:
protected void Application_Start()
{
Mapper.CreateMap<ProductDAO, ProductDTO>();
}
This will setup the mapping between these objects using the following conventions:
- Matching property names
- Nested property names (
Product.Name
maps to ProductName
, by assuming a Pascal case naming convention) - Methods starting with the word Get, so
GetTotal()
maps to Total
- Any existing type map already configured
Custom Formatters
AutoMapper also provides another extremely powerful capability called "Custom Formatters". Custom Formatters can step in during the mapping process and format the data being mapped in any way that you want. For a practical example, the code below is a mapping between a Model object and a ViewModel object that will be used on a "View" in an ASP.NET MVC application. The "Message
" property contains a comment that was entered by a website visitor, and therefore it needs to be HTML encoded. To set this up for the Message
property only, we would write this code in the Application_Start
method:
Mapper.CreateMap<Comment, CommentViewModel>()
.ForMember(c => c.Message, m =>
m.AddFormatter<htmlencodeformatter>());
public class HtmlEncodeFormatter : IValueFormatter
{
public string FormatValue(ResolutionContext context)
{
return HttpContext.Current.Server.HtmlEncode(
context.SourceValue.ToString());
}
}
In the example above, you'll notice that when we create the map between the Comment
and CommentViewModel
objects, that we singled out one of the properties (the Message
property, in this case) to be formatted using the HtmlEncodeFormatter
.
You can also setup global formatters that will be applied during every mapping operation. One common scenario that can be addressed by this feature is the case where you want to display all dates in the exact same format. This is extremely easy to setup as well:
Mapper.AddFormatter<DateStringFormatter>();
public class DateStringFormatter : BaseFormatter<DateTime?>
{
protected override string FormatValueCore(DateTime value)
{
return value.ToString("dddd, MMM dd, yyyy");
}
}
public abstract class BaseFormatter<T> : IValueFormatter
{
public string FormatValue(ResolutionContext context)
{
if (context.SourceValue == null)
return null;
if (!(context.SourceValue is T))
return context.SourceValue ==
null ? String.Empty : context.SourceValue.ToString();
return FormatValueCore((T)context.SourceValue);
}
protected abstract string FormatValueCore(T value);
}
In the example above, the first line is the one that actually registers the global formatter. The DateStringFormatter
and BaseFormatter
classes are what actually do the work.
First, and explanation of the BaseFormatter
class. The class implements the IValueFormatter
interface which an AutoMapper interface... this is what makes this class recognizable as a formatter in AutoMapper's eyes. I've made this class abstract so that we can handle all of the common checks that we need to handle: null checks, is it the right type, etc. The last line of the FormatValue
method calls the FormatValueCore
method that is defined as an abstract
method on this class. This is what provides the "hook" for our implementation class: DateStringFormatter
. All the DateStringFormatter
class nees to do is inherit the BaseFormatter
class, specify the actual type
being formatted (DateTime
in this case), and override the FormatValueCore
method. Once in this method, you can see that all we need to do is format the date in the way we want.
**One very important rule to remember: Formatters are only applied when the destination member type is of type "string
".
Conclusion
Using custom formatters within AutoMapper is a very simple that you can use AutoMapper to its full potential. There are a number of other great features in AutoMapper (Custom Value Resolvers, Custom Type Converters, Custom Actions before/after mapping, etc.) - but those are outside of the scope of this article. See the project website on CodePlex for more information: http://www.codeplex.com/AutoMapper.