简体   繁体   English

AutoMapper ForMember 方法破坏了映射的功能

[英]AutoMapper ForMember method breaks the functionality of mapping

I want to use AutoMapper in my.Net 6 APIs to convert the entity model User to DTO model UserDTO .我想在 my.Net 6 API 中使用 AutoMapper 将实体模型User转换为 DTO 模型UserDTO
The User model class is: User模型类是:

public class User : BaseEntity
{
  public Guid Id { get; set; }
  public string FirstName { get; set; } = null!;
  public string LastName { get; set; } = null!;
  public string Avatar { get; set; } = null!;
  public string Email { get; set; } = null!;
  public ICollection<Book>? FavoriteBooks { get; set; }
}

And the UserDTO is a record as follows:UserDTO是一条记录如下:

public record UserDTO(Guid Id, string FullName, string Avatar, string Email);

I have added the required package AutoMapper.Extensions.Microsoft.DependencyInjection v.12.0.0, and the configuration steps are given below:我添加了需要的包AutoMapper.Extensions.Microsoft.DependencyInjection v.12.0.0,配置步骤如下:
1- Create MappingProfile that inherits from the Profile class 1- 创建继承自Profile类的MappingProfile

public class MappingProfiles : Profile
{
  public MappingProfiles()
  {
    CreateMap<User, UserDTO>()
      .ForMember(
          dest => dest.FullName,
          opt => opt.MapFrom(src => string.Join(" ", src.FirstName, src.LastName))
      );
  }
}

2- Register the service in Program.cs file: 2- 在Program.cs文件中注册服务:

builder.Services.AddAutoMapper(typeof(Program));

3- Use the mapper as an injected service inside Service project: 3- 使用映射器作为Service项目中的注入服务:

public IEnumerable<UserDTO> GetAllUsers(bool trackChanges)
{
   var users = _repository.User.GetAllUsers(trackChanges);
   return _mapper.Map<IEnumerable<UserDTO>>(users);
}

When I call the GetAllUsers method in postman, I get the following error:当我在邮递员中调用GetAllUsers方法时,出现以下错误:

Error mapping types.错误映射类型。
Mapping types:映射类型:
List -> IEnumerable列表 -> IEnumerable

After a few days of struggling and searching, I realized that the .ForMember() method breaks the functionality of the profile class.经过几天的努力和搜索,我意识到.ForMember()方法破坏了配置文件类的功能。 In other words, if I change the UserDTO record:换句话说,如果我更改UserDTO记录:

public record UserDTO(Guid Id, string FirsName, string Avatar, string Email);

the FullName filed changed to FirstName to have compatibility with the User model. FullName更改为FirstName以与User模型兼容。 Also change the MappingProfile class:同时更改MappingProfile类:

public class MappingProfiles : Profile
{
  public MappingProfiles()
  {
    CreateMap<User, UserDTO>();
  }
}

the GetAllUsers method works as expected. GetAllUsers方法按预期工作。 So to conclude, if I add the .ForMember() method to the constructor of the MappingProfile class as in documentation, it breaks the functionality of the CreatMap method.因此总而言之,如果我像文档中那样将.ForMember()方法添加到MappingProfile类的构造函数,它会破坏CreatMap方法的功能。

How should I use the .ForMember() method to map the User model to the corresponding DTO?我应该如何使用.ForMember()方法将User模型映射到相应的 DTO? Is this method obsolete?这种方法过时了吗? Is there any replacement for this method?这种方法有什么替代方法吗?

I found 2 solutions:我找到了 2 个解决方案:

Solution 1:解决方案 1:
I created a method to get the full name of the user.我创建了一个方法来获取用户的全名。 The method name should be prefixed with get:方法名称应以 get 为前缀:

The naming convention can cover simpler examples where the source object has a property, method, or method with a “Get” as a prefix with the same name as the property of a destination object.命名约定可以涵盖更简单的示例,其中源对象具有属性、方法或以“Get”作为前缀的方法,其名称与目标对象的属性相同。

so I have modified the User model class and added the following method:所以我修改了User模型类并添加了以下方法:

public class User : BaseEntity
{
    ... // User model properties
    public string GetFullName() => $"{this.FirstName} {this.LastName}";
}

and removed the.ForMemeber()` method from the profile class:并从配置文件类中删除了 .ForMemeber()` 方法:

public MappingProfiles()
{
    CreateMap<User, UserDTO>();
}

Solution 2:解决方案 2:
It seems that .ForMember() is obsolete, I have found an alternative for that, .ForCtorParam() :似乎.ForMember()已经过时了,我找到了一个替代方案, .ForCtorParam()

public MappingProfiles()
{
    CreateMap<User, UserDTO>()
      .ForCtorParam(
          "FullName",
          opt => opt.MapFrom(src => string.Join(" ", src.FirstName, src.LastName))
      );
}

In these ways, I have converted my User model class to UserDTO .通过这些方式,我将我的User模型类转换为UserDTO

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM