从源映射到现有目标时,AutoMapper 不会忽略 List

Posted

技术标签:

【中文标题】从源映射到现有目标时,AutoMapper 不会忽略 List【英文标题】:AutoMapper does not ignore List when mapping from source to existing destination 【发布时间】:2022-01-23 21:56:28 【问题描述】:

我在使用 AutoMapper 时遇到了一个小问题。如果它确实是一个问题而不仅仅是一个误解,我已经将我面临的问题隔离开来。

以下是我正在使用的课程:

public class DemoEntity

    public List<string> Items  get; set; 
    public string Name  get; set; 


public class DemoDto

    public List<string> Items  get; set; 
    public string Name  get; set; 


public class DemoProfile : Profile

    public DemoProfile()
    
        CreateMap<DemoDto, DemoEntity>()
            .ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null));
    

在依赖注入部分(似乎在 .NET 6 的 Program.cs 中,但在我的主项目的 Startup.cs 中),我读过的这段代码应该有助于允许可空集合:

builder.Services.AddAutoMapper(configAction =>  configAction.AllowNullCollections = true; , typeof(Program));

这是我的测试代码:

var dto = new DemoDto();
var entity = new DemoEntity()

    Items = new List<string>()  "Some existing item" ,
    Name = "Existing name"
;

// Works as expected
var newEntity = _mapper.Map<DemoEntity>(dto);

// Sets the entity.Items to an empty list
_mapper.Map(dto, entity);

正如您在 DemoProfile 构造函数中看到的那样,我将条件设置为仅在 srcMember != null 时进行映射,这适用于 Name 属性。使用服务注册中的 AllowNullCollections,我可以映射到具有空列表的新对象(如果没有 AllowNullCollections 部分,它将是一个空列表)。

我的预期结果是 AutoMapper 会看到 dto.Items 为空,并且在映射期间不触及 entity.Items 属性,并在列表中保留 1 个字符串。实际结果是 entity.Items 是一个包含 0 个项目的列表。名称属性被忽略。

我错过了什么吗?如何调整我的代码以使 AutoMapper 在映射现有目的地时忽略一个为空的列表?

【问题讨论】:

【参考方案1】:

当源的成员(带有数组,List)为空或为空时,您可以查找PreCondition 以防止从源映射。

CreateMap<DemoDto, DemoEntity>() 
    .ForMember(dest => dest.Items, opt => opt.PreCondition((source, dest) => 
    
        return source.Items != null && source.Items.Count > 0;
    ))
    .ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null));

Sample demo on .NET Fiddle

【讨论】:

这似乎可行,我现在将使用它作为解决方法:) 谢谢!但我必须记住将此前提条件添加到包含列表的所有属性中。有没有更通用的方法?你对我的代码为什么不起作用有任何线索吗? 嗯,正如我之前尝试过的 PreCondition 是不可能的(如果我错了,请纠正我)。我认为数组字段不能像by default Automapper will assign empty array to destination if the source value was null那样正常工作。

以上是关于从源映射到现有目标时,AutoMapper 不会忽略 List的主要内容,如果未能解决你的问题,请参考以下文章

AutoMapper - 将源列表映射到目标数组

Automapper 忽略 null 值,但将空字符串映射到 null

Automapper 自定义解析器源成员到目标对象列表映射问题

[使用Automapper时,我是否也应该展平/映射视图模型的内部objetc?

09.AutoMapper 之自定义类型转换器(Custom Type Converters)

如何防止 AutoMapper 覆盖目标对象上的现有值?