使用 Auto Mapper 自定义解析
Custom resolving using Auto Mapper
我在应用程序的某些层中有以下 class 结构(我们称它为第一个):
public class Participant
{
public int Id { get; set; }
public string Name { get; set; }
public virtual User User { get; set; }
public virtual Conversation Conversation { get; set; }
public virtual ICollection<Message> Messages { get; set; }
}
public class User
{
public int Id { get; set; }
public string Login { get; set; }
public virtual ICollection<Participant> Participants { get; set; }
}
public class Conversation
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<Participant> Participants { get; set; }
}
这里是另一层class结构(第二层):
public class Participant
{
public int Id { get; set; }
public string Name { get; set; }
public User User { get; set; }
public ICollection<Message> Messages { get; set; }
}
public class User
{
public int Id { get; set; }
public string Login { get; set; }
public ICollection<Conversation> Conversations { get; set; }
}
public class Conversation
{
public int Id { get; set; }
public string Title { get; set; }
public ICollection<Participant> Participants { get; set; }
}
除了一些细节外,它们非常相似,最重要的是第二个用户 class 可以直接访问对话,而第一个用户可以仅访问参与者的实例。
我必须将第一个用户的实例映射到第二个用户。由于直接的映射方式行不通,我决定以下算法可能会起作用:
当我们必须将第一个用户映射到第二个用户时,获取第一个用户的所有参与者,获取每个参与者的对话并将其分配给第二个用户。每个 Conversation 也需要转换,并且此对话的 Participants 集合也必须转换。我尝试在没有任何映射库的情况下做到这一点,但 运行 进入无限递归,因为为了转换 First Conversation => Second Conversation,我们必须转换 Participants。要转换参与者,需要转换他们的对话等。
据我所知,AutoMapper可以无限递归处理简单的问题;然而,由于我的映射有点复杂,AM 在没有我帮助的情况下无法弄清楚如何映射 classes。
不幸的是,我无法弄清楚如何实现这种映射。我已经查看了 this guide,我想这就是我需要的,但我根本不知道如何编写这个映射,以便它将 classes 正确映射而不是 运行 到无限像我以前的解决方案一样递归。
如果有人可以提供有关如何实现此类映射的任何想法,我将很高兴。
您只需要通知 AutoMapper 如何映射不明显的属性,在本例中是您的用户 class。为了便于阅读,我已将 "second" 层中的所有 classes 重命名为 xxxDTO。
Mapper.CreateMap<Conversation, ConversationDTO>();
Mapper.CreateMap<Participant, ParticipantDTO>();
Mapper.CreateMap<User, UserDTO>()
.ForMember(dest => dest.Conversations,opt => opt.MapFrom(src => src.Participants.Select(p => p.Conversation)));
Mapper.CreateMap<Message, MessageDTO>();
如果一个用户有可能通过多个参与者链接到一个对话,那么您可以在 Select(p => p.Conversation)
之后添加一个 .Distinct()
。
我在应用程序的某些层中有以下 class 结构(我们称它为第一个):
public class Participant
{
public int Id { get; set; }
public string Name { get; set; }
public virtual User User { get; set; }
public virtual Conversation Conversation { get; set; }
public virtual ICollection<Message> Messages { get; set; }
}
public class User
{
public int Id { get; set; }
public string Login { get; set; }
public virtual ICollection<Participant> Participants { get; set; }
}
public class Conversation
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<Participant> Participants { get; set; }
}
这里是另一层class结构(第二层):
public class Participant
{
public int Id { get; set; }
public string Name { get; set; }
public User User { get; set; }
public ICollection<Message> Messages { get; set; }
}
public class User
{
public int Id { get; set; }
public string Login { get; set; }
public ICollection<Conversation> Conversations { get; set; }
}
public class Conversation
{
public int Id { get; set; }
public string Title { get; set; }
public ICollection<Participant> Participants { get; set; }
}
除了一些细节外,它们非常相似,最重要的是第二个用户 class 可以直接访问对话,而第一个用户可以仅访问参与者的实例。
我必须将第一个用户的实例映射到第二个用户。由于直接的映射方式行不通,我决定以下算法可能会起作用:
当我们必须将第一个用户映射到第二个用户时,获取第一个用户的所有参与者,获取每个参与者的对话并将其分配给第二个用户。每个 Conversation 也需要转换,并且此对话的 Participants 集合也必须转换。我尝试在没有任何映射库的情况下做到这一点,但 运行 进入无限递归,因为为了转换 First Conversation => Second Conversation,我们必须转换 Participants。要转换参与者,需要转换他们的对话等。
据我所知,AutoMapper可以无限递归处理简单的问题;然而,由于我的映射有点复杂,AM 在没有我帮助的情况下无法弄清楚如何映射 classes。
不幸的是,我无法弄清楚如何实现这种映射。我已经查看了 this guide,我想这就是我需要的,但我根本不知道如何编写这个映射,以便它将 classes 正确映射而不是 运行 到无限像我以前的解决方案一样递归。
如果有人可以提供有关如何实现此类映射的任何想法,我将很高兴。
您只需要通知 AutoMapper 如何映射不明显的属性,在本例中是您的用户 class。为了便于阅读,我已将 "second" 层中的所有 classes 重命名为 xxxDTO。
Mapper.CreateMap<Conversation, ConversationDTO>();
Mapper.CreateMap<Participant, ParticipantDTO>();
Mapper.CreateMap<User, UserDTO>()
.ForMember(dest => dest.Conversations,opt => opt.MapFrom(src => src.Participants.Select(p => p.Conversation)));
Mapper.CreateMap<Message, MessageDTO>();
如果一个用户有可能通过多个参与者链接到一个对话,那么您可以在 Select(p => p.Conversation)
之后添加一个 .Distinct()
。