Kash Farooq's software development blog

.NET Developer

Posts Tagged ‘AutoMapper’

AutoMapper: Mapping nested complex types

Posted by Kash Farooq on August 20, 2012

Some production code I was working on ¬†wasn’t working as expected, so I thought I’d spike it out.

AutoMapper allows you to map between, say, a service layer and a DTO without you having to write hardly any code. Install it with NuGet.

Here is an example. I have some types in my service layer:


namespace Automapper.Spike.Example1.Contract
{
  public class CreateOrderRequest
  {
    public int Id { get; set; }
    public int NumberOfItems { get; set; }
    public Customer Customer { get; set; }
  }

  public class Customer
  {
    public int Id { get; set; }
    public string FullName { get; set; }
    public string Postcode { get; set; }
   }
}

I want to map these to a DTO layer for storage:


namespace Automapper.Spike.Example1.Dto
{
  public class Order
  {
    public int Id { get; set; }
    public int NumberOfItems { get; set; }
    public Customer Customer { get; set; }
  }

  public class Customer
  {
    public int Id { get; set; }
    public string Name { get; set; }
    public string Postcode { get; set; }
  }
}

I just need to tell AutoMapper that I want it to map between these types:


public class MapperConfiguration
{
  public void Configure()
  {
    Mapper.CreateMap<Customer, Dto.Customer>()
      .ForMember(x=>x.Name,o=>o.MapFrom(src=>src.FullName));
    Mapper.CreateMap<CreateOrderRequest, Dto.Order>();
  }
}

That’s all the code you need. If FullName was just called Name, I wouldn’t even need the extra ForMember line.

Here is a test to check it all works:


[TestFixture]
public class Example1Test
{
  [Test]
  public void CheckMappings()
  {
    new MapperConfiguration().Configure();
    try
    {
      Mapper.AssertConfigurationIsValid();
    }
    catch (Exception e)
    {
      Console.WriteLine(e);
      Console.WriteLine(e.InnerException);
      throw;
    }

    var createOrderRequest = CreateTestOrderRequest();
    var order = Mapper.Map<Order>(createOrderRequest);

    order.Customer.Should().NotBeNull();
    order.Customer.Id.Should().Be(3);
    order.Customer.Name.Should().Be("Bob Smith");
    order.Customer.Postcode.Should().Be("W1 1AA");
    order.Id.Should().Be(1);
    order.NumberOfItems.Should().Be(2);
  }

  private static CreateOrderRequest CreateTestOrderRequest()
  {
    return new CreateOrderRequest
    {
      Id = 1,
      NumberOfItems = 2,
      Customer = new Customer
      {
        Id = 3,
        FullName = "Bob Smith",
        Postcode = "W1 1AA"
      }
    };
  }
}

Note the Mapper.AssertConfigurationIsValid() method. When you call this, AutoMapper will check you have provided enough configuration info.

Posted in .NET | Tagged: , , | Leave a Comment »