190

I am a newbie to the Automapper framework. I have a domain class and a DTO class as follows:

public class Employee
{
   public long Id {get;set;}
   public string Name {get;set;}
   public string Phone {get;set;}
   public string Fax {get;set;}
   public DateTime DateOfBirth {get;set;}
}

public class EmployeeDto
{
   public long Id {get;set;}
   public string FullName {get;set;}
   public DateTime DateOfBirth {get;set;}
}

Note: The name of property "Name" of Employee class is not the same as that of property "FullName" of EmployeeDto class.

And here's the code to map the Employee object to EmployeeDto:

Mapper.CreateMap<Employee, EmployeeDto>(); // code line (***)
EmployeeDto dto = Mapper.Map<Employee, EmployeeDto>(employee); 

My question is: If I want to map Employee (source class) to EmployeeDto (destination class), how can I specify the mapping rule? In other words, how should I do more with code line (***) above?

Anderson Pimentel
  • 5,086
  • 2
  • 32
  • 54
Thomas.Benz
  • 8,381
  • 9
  • 38
  • 65

6 Answers6

376

Never mind, I myself found a solution:

Mapper.CreateMap<Employee, EmployeeDto>()
    .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => src.Name));
Thomas.Benz
  • 8,381
  • 9
  • 38
  • 65
  • 1
    Is there a way to specify it globally for any class, something like prefix/suffix thing? For example, I have a bunch of classes fro a library that have "Localizations" property each. And I want to map them to classes where corresponding property is called "LocalizedName". Is my only option is to add ForMember to each mapping configuration? – NickAb May 20 '16 at 14:43
  • 2
    there is no CreateMap method in Mapper class :( – Navid_pdp11 Jul 20 '16 at 08:01
  • 3
    @Navid_pdp11 yes there is. You need to have the static class Mapper not an instance – Jordy van Eijk Jul 28 '16 at 11:42
  • @JordyvanEijk What version are you using that has a static "CreateMap" method? In 5.1.1.0 there's no such thing – Matt Thomas Oct 06 '16 at 19:42
  • @MattThomas As long as i can remember the CreateMap is a static method on the Mapper class at the moment i'm using 4.1.1 for a project but i dont know about the newer ones! – Jordy van Eijk Oct 10 '16 at 11:56
  • 6
    @MattThomas After taking a look at the github of automapper i see that as of version 5.0 CreateMap is obsolete and they say you need to use the MapperConfiguration or Mapper.Initialize. – Jordy van Eijk Oct 10 '16 at 12:00
  • I've never used AutoMapper before, I'm reading [this](https://github.com/AutoMapper/AutoMapper.EF6) and I'm wondering, can Does AutoMapper control the way EF treats my properties? My question is if I can select just the `FullName` property in the above example, or it will be `null`. – Shimmy Weitzhandler Apr 19 '17 at 00:04
  • Hi, What if we have many properties we want to map using ForMember. is there any efficient way to do that? rather than copy pasting line for a number of properties. – Khawaja Asim May 05 '17 at 12:47
  • is it possible to map a few diff members, but ensure all other identically named members also get mapped? – Sonic Soul May 24 '17 at 16:17
  • @NickAb One option might be to use an [`INamingConvention`](https://stackoverflow.com/a/2186232/712526). – jpaugh Mar 13 '18 at 15:58
17

Just to roll the comments above into an updated approach using Automapper 8.1+...

var mapConfig = new MapperConfiguration(
   cfg => cfg.CreateMap<Employee, EmployeeDto>()
      .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => src.Name))
);

Then you would build the mapper using the mapConfig:

var mapper = mapConfig.CreateMapper();
TylerH
  • 20,799
  • 66
  • 75
  • 101
ebol2000
  • 1,195
  • 11
  • 16
8

We can also specify on Class attributes for mapping

From https://docs.automapper.org/en/stable/Conventions.html#attribute-support

Attribute Support

AddMemberConfiguration().AddName<SourceToDestinationNameMapperAttributesMember>(); * Currently is always on

Looks for instances of SourceToDestinationMapperAttribute for Properties/Fields and calls user defined isMatch function to find member matches.

MapToAttribute is one of them which will match the property based on name provided.

public class Foo
{
    [MapTo("SourceOfBar")]
    public int Bar { get; set; }
}
TylerH
  • 20,799
  • 66
  • 75
  • 101
Pranay DevOps
  • 81
  • 1
  • 3
3

Considering that we have two classes

public class LookupDetailsBO
    {
        public int ID { get; set; }

        public string Description { get; set; }

    }

and the other class is

public class MaterialBO
    {
        [MapTo(nameof(LookupDetailsBO.ID))]
        public int MaterialId { get; set; }

        [MapTo(nameof(LookupDetailsBO.Description))]
        public string MaterialName { get; set; }

        public int LanguageId { get; set; }
    }

In this way you know typically to which property you follow . and you make sure of the naming convention , so if you have changed the propery name in the source . The MapTo() will prompt an error

2

The new style of Attribute Mapping via Data Annotations:

https://docs.automapper.org/en/v8.1.0/Attribute-mapping.html?highlight=annotation

   [AutoMap(typeof(Order))]
   public class OrderDto {
      // This is equivalent to a CreateMap<Order, OrderDto>() 

For mapping the member

   [SourceMember(nameof(Order.OrderTotal))]
   public decimal Total { get; set; }

If you want reverse map then you add that property in

   [AutoMap(typeof(Order), ReverseMap = true )]
   public class OrderDto {
      // This is equivalent to a CreateMap<Order, OrderDto>().ReverseMap() 
Wild Bill
  • 51
  • 1
  • 3
1

The above answers are great and hope OP has got his answer. I just want to add how we can map fixed values instead of fields using UseValue() method of IMemberConfigurationExpression Interface.

Mapper.CreateMap<Employee, EmployeeDto>()
    .ForMember(dest => dest.Department, opt => opt.UseValue("Development"));

This will map "Development" as a Department property value for destination data.

quasar
  • 404
  • 6
  • 17