AutoMapper
In this post I want to overview AutoMapper library.
AutoMapper is open-source project for object-to-object mapping.
It uses very nice syntax for mapping configuration based on generic and lambda.
The project is managed on Codeplex (http://www.codeplex.com/AutoMapper) and the source code can be found at GoogleCode (http://automapperhome.googlecode.com/).
Object mapping is very useful strategy for transforming one type of object into another.
For ex. Business Object into POCO (CLR POJO) or DTO (Data Transfer Object).
Lets define application domain:
//Business Object
public class Task
{
public string Name { get; set; }
public DateTime DueTo { get; set; }
public string GetDetails() { return "details"; }
public TaskPriority Priority { get; set; }
//...
}
//DTO
public class TaskDto
{
public string Name { get; set; }
public string DueTo { get; set; }
public string Details { get; set; }
public string PriorityCaption { get; set; }
}
public class TaskPriority
{
public TaskPriority() {}
public TaskPriority(string caption)
{
Caption = caption;
}
public string Caption { get; set; }
}
Manual conversion code will look like following:
public static TaskDto MapManual(Task task)
{
return new TaskDto
{
Name = task.Name,
DueTo = task.DueTo.ToLongDateString(),
Details = task.GetDetails(),
PriorityCaption = task.Priority.Caption
};
}
And now with AutoMapper:
TaskDto taskDto = Mapper.Map<Task, TaskDto>(task);
Of course before need to define mapping configuration:
public static void InitMappings()
{
Mapper.CreateMap<Task, TaskDto>();
//Recommended to check if the configuration is valid
Mapper.AssertConfigurationIsValid();
}
AutoMapper supports default mappings like matching property names, mapping method GetX() to property X, nested properties (Priority.Caption maps to PriorityCaption by assuming a PascalCase naming convention) and etc.
If default mappings and default conversions are not enough, possible to use custom converters or custom mapping configuration.
Let's write custom converter - for ex. from DateTime to string (DueTo property)
First implement type converter:
public class DateTimeTypeConverter : TypeConverter<DateTime, string>
{
protected override string ConvertCore(DateTime source)
{
return source.ToLongDateString();
}
}
And add to mapping configuration:
public static void InitMappins()
{
Mapper.CreateMap<DateTime, string>().ConvertUsing(new DateTimeTypeConverter());
Mapper.CreateMap<Task, TaskDto>();
Mapper.AssertConfigurationIsValid();
}
Now let's write custom mapping configuration:
public static void InitMappings()
{
Mapper.CreateMap<DateTime, string>().ConvertUsing(new DateTimeTypeConverter());
Mapper.CreateMap<Task, TaskDto>()
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name))
.ForMember(dest => dest.DueTo, opt => opt.MapFrom(src => src.DueTo))
.ForMember(dest => dest.Details, opt => opt.MapFrom(src => src.GetDetails()))
.ForMember(dest => dest.PriorityCaption, opt => opt.MapFrom(src => src.Priority.Caption));
Mapper.AssertConfigurationIsValid();
}
General AutoMapper features:
Flattening
Projection
Configuration Validation
Lists and Arrays
Nested Mappings
Custom Type Converters
Custom Value Resolvers
Custom Value Formatters
Null Substitution
Currently the project documentation is not full but covers basic features.
In additional possible to lean a lot from source code that consists samples and unit tests.
Alternative tools:
BLToolkit http://bltoolkit.net
EmitMapper http://emitmapper.codeplex.com
Path to source http://github.com/lm2000/AutoMapperStuff
