如何在 AutoMapper 映射中忽略 属性 的 属性?
How to ignore property of property in AutoMapper mapping?
图像Person
和Group
class具有多对多关系。一个人有一个组列表,一个组有一个人列表。
当映射 Person
到 PersonDTO
我有一个 stack overflow exception
因为 AutoMapper 不能处理 Person
>Groups
>Members
>Groups
>Members
>...
下面是示例代码:
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; }
}
当我使用 .ForMember 创建映射器时,第一个执行的映射器抛出 null reference exception
.
这是映射器的代码:
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();
那么我错过了什么或做错了什么?当我删除 .ForMember 方法时,不再抛出 null reference exception
。
更新:我真的想强调我的问题的要点是如何忽略[= 属性 的 56=]。此代码只是一个相当简单的示例。
更新 2:这就是我修复它的方法,非常感谢 Lucian-Bargaoanu
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();
感谢 .PreserveReferences()
循环引用得到修复!
我认为您遇到的问题来自错误的假设,即 PersonDTO.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; }
}
(名字当然由你决定)只识别组而不传递额外的成员。
这应该行得通。参见 https://github.com/AutoMapper/AutoMapper/wiki/5.0-Upgrade-Guide#circular-references. There is also a PR pending https://github.com/AutoMapper/AutoMapper/pull/2233。
图像Person
和Group
class具有多对多关系。一个人有一个组列表,一个组有一个人列表。
当映射 Person
到 PersonDTO
我有一个 stack overflow exception
因为 AutoMapper 不能处理 Person
>Groups
>Members
>Groups
>Members
>...
下面是示例代码:
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; }
}
当我使用 .ForMember 创建映射器时,第一个执行的映射器抛出 null reference exception
.
这是映射器的代码:
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();
那么我错过了什么或做错了什么?当我删除 .ForMember 方法时,不再抛出 null reference exception
。
更新:我真的想强调我的问题的要点是如何忽略[= 属性 的 56=]。此代码只是一个相当简单的示例。
更新 2:这就是我修复它的方法,非常感谢 Lucian-Bargaoanu
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();
感谢 .PreserveReferences()
循环引用得到修复!
我认为您遇到的问题来自错误的假设,即 PersonDTO.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; }
}
(名字当然由你决定)只识别组而不传递额外的成员。
这应该行得通。参见 https://github.com/AutoMapper/AutoMapper/wiki/5.0-Upgrade-Guide#circular-references. There is also a PR pending https://github.com/AutoMapper/AutoMapper/pull/2233。