简单的自动映射器示例

Posted

技术标签:

【中文标题】简单的自动映射器示例【英文标题】:Simple Automapper Example 【发布时间】:2014-01-05 07:07:11 【问题描述】:

我很难理解如何映射某些对象。请回答有关这个简单示例的一些问题。

示例代码

class User

    private int id;
    private string name;


class Group

    private int id;
    private string name;
    private List<User> users;


[DataContract]
public class UserDto

    [DataMember]
    public int id  get; set; 
    [DataMember]
    public string name get; set;       


[DataContract]
public class GroupDto

    [DataMember]
    public int id  get; set; 
    [DataMember]
    public string name get; set; 
    [DataMember]
    public List<User> Users  get; set;       

映射器

Mapper.CreateMap<User, UserDto>();
Mapper.CreateMap<UserDto, User>();

Mapper.CreateMap<Group, GroupDto>();
Mapper.CreateMap<GroupDto, Group>();

在将Group 映射到GroupDto 时,是否必须在内部将User 映射到UserDto,因为Group 中的List&lt;User&gt; 包含未映射的Users?如果是这样,你如何做到这一点?我的猜测是

Mapper.CreateMap<Group, GroupDto>()
    .ForMember(g => g.id, opt => opt.Ignore());
    .ForMember(g => g.name, opt => opt.Ignore());
    .ForMember(g => g.Users, opt => opt.MapFrom(u => Mapper.Map<Group, UserDto>(u)))

这对吗?

【问题讨论】:

为什么您的 GroupDTO 不包含 UserDTO?如果是这样,除了CreateMap 之外,AutoMapper 就不需要其他配置了。 这是我用 C# 写的关于 Automapper 的简单文章codeproject.com/Articles/986460/What-is-Automapper 阅读本文:codearsenal.net/2012/12/… 如果有上面发布的文章的更新副本会有所帮助。我不相信它在 AutoMapper 5.x 中有效。 【参考方案1】:

1- 将 GroupD 更改为如下所示:

[DataContract]
public class GroupDto

    [DataMember]
    public int id  get; set; 
    [DataMember]
    public string name get; set; 
    [DataMember]
    public List<UserDTO> Users  get; set;       

2- 创建您的映射:

Mapper.CreateMap<User, UserDto>();
Mapper.CreateMap<UserDto, User>(); // Only if you convert back from dto to entity

Mapper.CreateMap<Group, GroupDto>();
Mapper.CreateMap<GroupDto, Group>(); // Only if you convert back from dto to entity

3- 仅此而已,因为自动映射器会自动将 List&lt;User&gt; 映射到 List&lt;UserDto&gt;(因为它们具有相同的名称,并且已经存在从 user 到 UserDto 的映射)

4- 当你想映射时,你打电话:

Mapper.Map<GroupDto>(groupEntity);

希望对您有所帮助。

【讨论】:

"因为他们有相同的名字," -- 类型也重要吗?如果一个对象是list,另一个是ICollection,是否需要成员映射? 我希望看到 AutoMapper 5 的更新示例。我认为其中大部分不再有效。【参考方案2】:

正如@stuartd 所说,如果你改变:

[DataContract]
public class GroupDto

    [DataMember]
    public int id  get; set; 
    [DataMember]
    public string name get; set; 
    [DataMember]
    public List<User> Users  get; set;       

为:

[DataContract]
public class GroupDto

    [DataMember]
    public int id  get; set; 
    [DataMember]
    public string name get; set; 
    [DataMember]
    public List<UserDTO> Users  get; set;       

你只需要:

Mapper.CreateMap()

否则,改变

Mapper.CreateMap<Group, GroupDto>()
    .ForMember(g => g.id, opt => opt.Ignore());
    .ForMember(g => g.name, opt => opt.Ignore());
    .ForMember(g => g.Users, opt => opt.MapFrom(u => Mapper.Map<Group, UserDto>(u)))

对于类似的东西:

Mapper.CreateMap<Group, GroupDto>()
    .ForMember(g => g.id, opt => opt.Ignore());
    .ForMember(g => g.name, opt => opt.Ignore());
    .ForMember(g => g.Users, opt => opt.MapFrom(u => Mapper.Map<List<User>>(g.Users)))

这个还没有测试过,但是思路就在这里....

【讨论】:

以上是关于简单的自动映射器示例的主要内容,如果未能解决你的问题,请参考以下文章

使用自动映射器映射对象列表

Keycloak 中的协议映射器如何工作?

PHP面向对象之领域模型+数据映射器

无法使用自动映射器映射内部导航属性。 EF 核心

防止 Mapstruct 在自动映射器检测中使用方法

自动映射器。来自 json 的映射属性