当属性名称不同时如何指定映射规则

193

我对Automapper框架还是个新手。我有一个领域类和一个DTO类,如下所示:

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;}
}

注意:Employee类的属性"Name"EmployeeDto类的属性"FullName"不同。

以下是将Employee对象映射到EmployeeDto的代码:

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

我的问题是:如果我想将Employee(源类)映射到EmployeeDto(目标类),我应该如何指定映射规则?换句话说,我应该如何更改上面的代码行(***)?

6个回答

380

没关系,我自己找到了解决方法:

Mapper.CreateMap<Employee, EmployeeDto>()
    .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => src.Name));

1
有没有一种方法可以全局指定任何类的前缀/后缀之类的东西?例如,我有一个库中的一堆类,每个类都有“Localizations”属性。我想将它们映射到相应属性称为“LocalizedName”的类。我的唯一选择是为每个映射配置添加ForMember吗? - NickAb
2
Mapper类中没有CreateMap方法 :( - Navid_pdp11
3
@Navid_pdp11,是的,有一个需要使用静态类 Mapper 而不是实例。 - Jordy van Eijk
6
经查看AutoMapper的GitHub页面,我发现自版本5.0以后CreateMap方法已经被弃用。该网页建议使用MapperConfiguration或Mapper.Initialize方法。 - Jordy van Eijk
能否将几个不同的成员映射起来,但又确保所有其他同名成员也得到映射? - Sonic Soul
显示剩余5条评论

18

只是将上面的评论汇总,以更新使用Automapper 8.1+的方法...

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

然后,您将使用mapConfig构建映射器:

var mapper = mapConfig.CreateMapper();

8
我们还可以指定类属性进行映射。
来自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
2
检查新样式 :) http://docs.automapper.org/en/latest/Attribute-mapping.html - Lucian Bargaoanu
非常新手,第一次使用stackoverflow。我一定会遵守规则的 @TylerH - Pranay DevOps
该链接现在是404。 - fullStackChris

3

考虑到我们有两个类

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

        public string Description { get; set; }

    }

另一个类别是

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; }
    }

通过这种方式,你通常知道你要遵循哪个属性,而且你确保命名规范,所以如果你在源代码中更改了属性名称,MapTo()会提示错误。


2
使用数据注释的新属性映射风格:

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>() 

“为成员进行映射”
   [SourceMember(nameof(Order.OrderTotal))]
   public decimal Total { get; set; }

如果您想要反向映射,那么您需要在其中添加该属性。
   [AutoMap(typeof(Order), ReverseMap = true )]
   public class OrderDto {
      // This is equivalent to a CreateMap<Order, OrderDto>().ReverseMap() 

1
上面的回答很好,希望楼主已经得到了答案。我想补充一下如何使用IMemberConfigurationExpression接口的UseValue()方法来映射固定值而不是字段。请保留HTML标签。
Mapper.CreateMap<Employee, EmployeeDto>()
    .ForMember(dest => dest.Department, opt => opt.UseValue("Development"));

这将把“开发”映射为目标数据的部门属性值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接