想象一个具有多对多关系的Person
和Group
类。一个人有一个组列表,一个组有一个人员列表。
将Person
映射到PersonDTO
时我有stack overflow exception
,因为AutoMapper无法处理Person
> Groups
> {{1 }}> Members
> Groups
> ...
以下是示例代码:
Members
当我在创建映射器时使用.ForMember时,第一个被执行的映射器会抛出public class Person
{
public string Name { get; set; }
public List<Group> Groups { get; set; }
}
public class Group
{
public string Name { get; set; }
public List<Person> Members { get; set; }
}
public class PersonDTO
{
public string Name { get; set; }
public List<GroupDTO> Groups { get; set; }
}
public class GroupDTO
{
public string Name { get; set; }
public List<PersonDTO> Members { get; set; }
}
。
这是映射器的代码:
null reference exception
那么我错过了什么或做错了什么?当我删除.ForMember方法时,CreateMap<Person, PersonDTO>()
.ForMember(x => x.Groups.Select(y => y.Members), opt => opt.Ignore())
.ReverseMap();
CreateMap<Group, GroupDTO>()
.ForMember(x => x.Members.Select(y => y.Groups), opt => opt.Ignore())
.ReverseMap();
不再被抛出。
更新:我真的想强调我的问题的要点是如何忽略属性的属性。这段代码只是一个相当简单的例子。
更新2:这是我修复它的方式,非常感谢Lucian-Bargaoanu
null reference exception
感谢CreateMap<Person, PersonDTO>()
.ForMember(x => x.Groups.Select(y => y.Members), opt => opt.Ignore())
.PreserveReferences() // This is the solution!
.ReverseMap();
CreateMap<Group, GroupDTO>()
.ForMember(x => x.Members.Select(y => y.Groups), opt => opt.Ignore())
.PreserveReferences() // This is the solution!
.ReverseMap();
循环引用得到修复!
答案 0 :(得分:2)
这应该可行。见https://github.com/AutoMapper/AutoMapper/wiki/5.0-Upgrade-Guide#circular-references。还有一个待定的https://github.com/AutoMapper/AutoMapper/pull/2233。
答案 1 :(得分:1)
我认为您遇到的问题来自错误的假设,即PersonDTO.Groups中的Groups与GroupDTO相同 - 没有无限依赖循环就不能这样。以下代码适合您:
CreateMap<Person, PersonDTO>()
.ForMember(x => x.Groups, opt => opt.Ignore())
.ReverseMap()
.AfterMap((src, dest) =>
{
dest.Groups = src.Groups.Select(g => new GroupDTO { Name = g.Name }).ToList()
});
CreateMap<Group, GroupDTO>()
.ForMember(x => x.Members, opt => opt.Ignore())
.ReverseMap()
.AfterMap((src, dest) =>
{
dest.Members = src.Members.Select(p => new PersonDTO { Name = p.Name }).ToList()
});
你基本上需要教AutoMapper,在PersonDTO.Groups属性的情况下,它应该以不同的方式映射GroupDTO对象。
但我认为你的问题更像是建筑问题,而不是代码问题。 PersonDTO.Groups不应该是GroupDTO类型 - 您只对特定用户所属的组感兴趣,而不是对其组的其他成员感兴趣。你应该有一些更简单的类型:
public class PersonGroupDTO
{
public string Name { get; set; }
}
(当然,这个名称取决于您)只能在不通过其他成员的情况下识别该组。