Friday 4 November 2011

More Advanced Use of AutoMapper - Part 1

Projection
public class Person
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
}

public class PersonViewModel
{
    public string FullName { get; set; }
    public int DayOfBirth { get; set; }
    public int MonthOfBirth { get; set; }
    public int YearOfBirth { get; set; }
    public string Email { get; set; }
}


Mapper.CreateMap<Person, PersonViewModel>()
    .ForMember(d => d.DayOfBirth, o => o.MapFrom(s => s.DateOfBirth.Day))
    .ForMember(d => d.MonthOfBirth, o => o.MapFrom(s => s.DateOfBirth.Month))
    .ForMember(d => d.YearOfBirth, o => o.MapFrom(s => s.DateOfBirth.Year))
    .ForMember(d => d.FullName, o => o.MapFrom(s => s.FirstName + " " + s.LastName))
    .ForMember(d => d.Email, o => o.Ignore());
AutoMapper needs to know how to map to ALL of the destination class members. It is fine if some source class' members do not have any match. In this case the source class Person has a PersonId member, however it is not used in the destination class. No mapping configuration is required, AutoMapper will automatically ignore it. However for the destination class member Email which do not have a match in the source class, it is necessary to specify a mapping configuration.


Collections
After a map is created, we can map a collection of source class' objects into a collection of destination class' objects without extra configuration.
var sources = new[]
    {
        new Person{PersonId =10, DateOfBirth=new DateTime(1910,10,1), FirstName="Johnny", LastName="King"},
        new Person{PersonId =11, DateOfBirth=new DateTime(1911,11,2), FirstName="Katherine", LastName="Wood"},
        new Person{PersonId =12, DateOfBirth=new DateTime(1912,12,3), FirstName="Sam", LastName="Bourke"}
    };
List<PersonViewModel> listPersonViewModels = Mapper.Map<Person[], List<PersonViewModel>>(sources);
Collection types supported are: IEnumerable, IEnumerable<T>, ICollection, ICollection<T>, IList, IList<T>, List<T> and Arrays.


Nested mappings
No mapping configuration is needed to map a nested class. As long as all of the destination class' members have matches, we just need to specify one more mapping for each nested class.
public class Outer
{
    public int Value { get; set; }
    public Nested InnerClass { get; set; }
}
public class Nested
{
    public int InnerValue { get; set; }
}

public class OuterViewModel
{
    public int Value { get; set; }
    public NestedViewModel InnerClass { get; set; }
}
public class NestedViewModel
{
    public int InnerValue { get; set; }
}


Mapper.CreateMap<Outer, OuterViewModel>();
// need to specify mapping for the nested class as well
Mapper.CreateMap<Nested, NestedViewModel>();


// usage
var source = new Outer
{
    Value = 5,
    InnerClass = new Nested { InnerValue = 15 }
};
var dest = Mapper.Map<Outer, OuterViewModel>(source);

Reference:
https://github.com/AutoMapper/AutoMapper/wiki

No comments: