Home > ASP.NET MVC, dotnet 4, SOLID > Automapper

Automapper

Recently a friend of mine was talking to me about his interesting project and in the conversation I mentioned him to use Automapper. As he was not aware of it but when I started explaining him he really got intrigued by it. I provided him the link and thought about blogging about it.

As you have guess it, it’s mainly a very smart mapping tool and will do all your left right hand code mapping. Whether it’s a MVC project where you do a lot of mapping between View-Model to DTO’s or whether you are working in an integration, this is something you can’t miss. You can download the assembly from codeplex at http://automapper.codeplex.com/releases/view/44802

Lets see some examples. Lets say i have two classes PersonDisplayVm & PersonDto and the dto instance is called item and the Vm instance is called model. So inorder to map the two objects so that we can copy value from dto to model we create a map between the classes and use the Map function to map it like this.

  Mapper.CreateMap<PersonDto, PersonDisplayVm>();
  Mapper.Map(item, model);

and this is how my two classes look like

public class PersonDisplayVm
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int? Age { get; set; }
    public DateTime CreatedDateTime { get; set; }
}

public class PersonDto : IPersonDto
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int? Age { get; set; }
    public DateTime CreatedDateTime { get; set; }
}

As you can see it already saved a lot of lines of code where we have to painstakingly assigning  value of one attribute in the left hand side to the corresponding value in the right hand side.

Following TDD and our good habit of writing test lets write a quick test.

[TestFixture]
public class When_testing_person_mapping
{
public PersonDto GetPersonDto()
{
     return new PersonDto
                {
                    Id = 1,
                    FirstName = "Joe",
                    LastName = "Blogg",
                    Age = 45,
                    CreatedDateTime = DateTime.Now
                };
}

[Test]
public void Should_be_able_to_map_dto_to_vm()
{
     var dto = GetPersonDto();
     var vm = new PersonDisplayVm();
     Mapper.CreateMap<PersonDto, PersonDisplayVm>();
     Mapper.Map(dto, vm);
     Assert.IsTrue(dto.Id == vm.Id);
}

Now lets say if for some reason in my display view-model I have the created datetime as string if we try to do a automapping from view-model to dto then we get an exception like

Exception of type ‘AutoMapper.AutoMapperMappingException’ was thrown.

as the string datetime when intialize with DateTime.Now add AM PM string into the string field and automapper can’t map it directly.In order to fix this problem you have to create a custom type convertor like this

public class DateTimeTypeConverter : ITypeConverter<string, DateTime>
{
    public DateTime Convert(ResolutionContext context)
    {
        return System.Convert.ToDateTime(context.SourceValue);
    }
}

And add the custom type converter before our mapping happens like this

[Test]
public void Should_be_able_to_map_dto_to_vm()
{
    var dto = GetPersonDto();
    var vm = new PersonDisplayVm();
    Mapper.CreateMap<string, DateTime>().ConvertUsing(new DateTimeTypeConverter());
    Mapper.CreateMap<PersonDto, PersonDisplayVm>();
    Mapper.Map(dto, vm);
    Assert.IsTrue(dto.Id == vm.Id);
}

And you will see our test this time passes with no exceptions.

Now lets say you have another system or some legacy code where the Person class returned has a PersonId field instead of Id and it would be real waste to write another class which looks like the legacy class and write the whole mapping yourself.

This is where some of extensibility point of this mapper comes into play so lets say your legacy class or any other class looks like this.

public class PersonLegacyDto
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int? Age { get; set; }
    public DateTime CreatedDateTime { get; set; }
}

to map the PersonId field to Id field in PersonDto class you can simple specify it like this.

[Test]
public void Should_be_able_to_map_legacy_to_dto()
{
    var dto = GetPersonDto();
    var personLegacy = GetLegacyPerson();
    Mapper.CreateMap<PersonLegacyDto, PersonDto>()
        .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.PersonId))
        ;

    Mapper.Map(personLegacy, dto);
}

and you will see it does rest of the stuff, the .ForMember is an fluent interface so you can chain them for multiple property mapping.I use it quite often as it saves tones of writing left hand right hand code and saves a lot of time and energy. Hope you will find it handy to use and although I am using it in MVC project but can be used in any service/data layer project as well.

Advertisements
  1. kaitlin
    November 22, 2010 at 3:28 pm

    great one

  2. frostwire download
    November 29, 2010 at 11:18 am

    one can argue that it can go both ways

  1. November 3, 2010 at 5:59 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: