AutoMapper.Collection - 如果源集合 属性 为空,则完全跳过映射
AutoMapper.Collection - Skip mapping entirely if source collection property is null
如果源集合 属性 为空,是否有任何方法可以让 AutoMapper.Collection 跳过集合的映射?
在我的例子中,客户端可能想向 API 发出信号,表明不需要更新给定的集合。一种合乎逻辑的方法是在客户端发送的 dto 中将集合 属性 设置为 null。
基本上:
- 如果源集合 属性 为空:根本不要触及目标集合,保持原样。 不要清除它
- 如果源集合不为空:做集合映射。如果源集合为空,这意味着清除目标集合
在AutoMapper.Collection中有什么方法可以做到这一点吗?我要找的是这个:
// Sample Classes
public class Entity
{
public ICollection<EntityChild> Children { get; set; }
}
public class EntityChild
{
public int Id { get; set; }
public string Value { get; set; }
}
public class Dto
{
public ICollection<DtoChild> Children { get; set; }
}
public class DtoChild
{
public int Id { get; set; }
public string Value { get; set; }
}
// AutoMapper setup including equality for children
CreateMap<Dto, Entity>();
CreateMap<DtoChild, EntityChild>()
.EqualityComparison((src, dst) => src.Id == dst.Id)
.ReverseMap();
// Sample 1, null source collection
var entity = new Entity
{
Children = new List<EntityChild>
{
new() { Id = 1, Value = "Value 1" },
new() { Id = 2, Value = "Value 2" }
}
};
var dtoSkipChildren = new Dto
{
Children = null
};
// Since the source Children property is null, do not update the destination collection
mapper.Map(dtoSkipChildren, entity);
// Sample 2, empty source collection
entity = new Entity
{
Children = new List<EntityChild>
{
new() { Id = 1, Value = "Value 1" },
new() { Id = 2, Value = "Value 2" }
}
};
var dtoClearChildren = new Dto
{
Children = new List<DtoChild>()
};
// Now the source children is not null (but empty) so the destination collection should
// be updated (in this case cleared since the source collection is empty)
mapper.Map(dtoClearChildren, entity);
AutoMapper.Collection 将空源 Children 属性 视为与包含空集合的源 Children 属性 相同。在这两种情况下,目标 Children 集合都会被清除。
我试图告诉 AutoMapper 跳过 source.Children 属性 if null:
CreateMap<Dto, Entity>()
.ForMember(dst => dst.Children, opt => opt.Condition(src => null != src.Children));
这不会改变任何事情。同样在这种情况下,当 AutoMapper.Collection 设置为工作并且目标集合被清除时,源集合 属性 为空。
这也不是真正的解决方案:
CreateMap<Dto, Entity>()
.ForMember(
src => src.Children,
opt => opt.MapFrom((src, dst, _, ctx) => src.Children ?? ctx.Mapper.Map<ICollection<DtoChild>>(dst.Children)));
这意味着将目标集合反向映射到(空)源集合,因此可以映射回来。一个丑陋的骇客:
- 它要过两次河才能到达你开始的地方
- 浪费精力,在大型集合上很愚蠢
- 有风险,因为其他原因的反向映射可能不是 100%,因此引入了相当隐藏的错误
有没有人对如何实现这一点有建议 - 或者为什么我的用例不是一个好主意?
我遇到了同样的问题,我是这样想出来的
CreateMap<Dto, Entity>()
.ForMember(
dest=> dest.Children,
opt => {
opt.PreCondition(src =>src.Children!= null);
opt.MapFrom(src =>src.Children);
});
然后在这个地方,你要使用映射写代码如下:
entity = mapper.Map<Dto, Entity>(dto , entity);
opt.PreCondition(src =>src.Children!= null)
基本上告诉 AutoMapper 如果源字段不为空则继续映射,否则不映射。
要阅读更多请看这个 https://docs.automapper.org/en/stable/Conditional-mapping.html#preconditions
如果源集合 属性 为空,是否有任何方法可以让 AutoMapper.Collection 跳过集合的映射?
在我的例子中,客户端可能想向 API 发出信号,表明不需要更新给定的集合。一种合乎逻辑的方法是在客户端发送的 dto 中将集合 属性 设置为 null。
基本上:
- 如果源集合 属性 为空:根本不要触及目标集合,保持原样。 不要清除它
- 如果源集合不为空:做集合映射。如果源集合为空,这意味着清除目标集合
在AutoMapper.Collection中有什么方法可以做到这一点吗?我要找的是这个:
// Sample Classes
public class Entity
{
public ICollection<EntityChild> Children { get; set; }
}
public class EntityChild
{
public int Id { get; set; }
public string Value { get; set; }
}
public class Dto
{
public ICollection<DtoChild> Children { get; set; }
}
public class DtoChild
{
public int Id { get; set; }
public string Value { get; set; }
}
// AutoMapper setup including equality for children
CreateMap<Dto, Entity>();
CreateMap<DtoChild, EntityChild>()
.EqualityComparison((src, dst) => src.Id == dst.Id)
.ReverseMap();
// Sample 1, null source collection
var entity = new Entity
{
Children = new List<EntityChild>
{
new() { Id = 1, Value = "Value 1" },
new() { Id = 2, Value = "Value 2" }
}
};
var dtoSkipChildren = new Dto
{
Children = null
};
// Since the source Children property is null, do not update the destination collection
mapper.Map(dtoSkipChildren, entity);
// Sample 2, empty source collection
entity = new Entity
{
Children = new List<EntityChild>
{
new() { Id = 1, Value = "Value 1" },
new() { Id = 2, Value = "Value 2" }
}
};
var dtoClearChildren = new Dto
{
Children = new List<DtoChild>()
};
// Now the source children is not null (but empty) so the destination collection should
// be updated (in this case cleared since the source collection is empty)
mapper.Map(dtoClearChildren, entity);
AutoMapper.Collection 将空源 Children 属性 视为与包含空集合的源 Children 属性 相同。在这两种情况下,目标 Children 集合都会被清除。
我试图告诉 AutoMapper 跳过 source.Children 属性 if null:
CreateMap<Dto, Entity>()
.ForMember(dst => dst.Children, opt => opt.Condition(src => null != src.Children));
这不会改变任何事情。同样在这种情况下,当 AutoMapper.Collection 设置为工作并且目标集合被清除时,源集合 属性 为空。
这也不是真正的解决方案:
CreateMap<Dto, Entity>()
.ForMember(
src => src.Children,
opt => opt.MapFrom((src, dst, _, ctx) => src.Children ?? ctx.Mapper.Map<ICollection<DtoChild>>(dst.Children)));
这意味着将目标集合反向映射到(空)源集合,因此可以映射回来。一个丑陋的骇客:
- 它要过两次河才能到达你开始的地方
- 浪费精力,在大型集合上很愚蠢
- 有风险,因为其他原因的反向映射可能不是 100%,因此引入了相当隐藏的错误
有没有人对如何实现这一点有建议 - 或者为什么我的用例不是一个好主意?
我遇到了同样的问题,我是这样想出来的
CreateMap<Dto, Entity>()
.ForMember(
dest=> dest.Children,
opt => {
opt.PreCondition(src =>src.Children!= null);
opt.MapFrom(src =>src.Children);
});
然后在这个地方,你要使用映射写代码如下:
entity = mapper.Map<Dto, Entity>(dto , entity);
opt.PreCondition(src =>src.Children!= null)
基本上告诉 AutoMapper 如果源字段不为空则继续映射,否则不映射。
要阅读更多请看这个 https://docs.automapper.org/en/stable/Conditional-mapping.html#preconditions