You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AutoMapper使用Ignore方法时目标属性被设为null的问题排查

AutoMapper Ignore方法导致目标属性被设为null的问题分析

我尝试用AutoMapper的Ignore()方法忽略目标属性,以保留它的原始值,多数情况这个方法有效,但有时会把目标属性值设为null。以下是复现代码,预期client.ContactDetails.First().Address的值为“Old”:

using AutoMapper;

class Program
{
    static void Main(string[] args)
    {
        ClientMapperProfile clientMapperProfile = new ClientMapperProfile();
        var configurationProvider = new MapperConfiguration(c => c.AddProfile(clientMapperProfile));
        Mapper mapper = new Mapper(configurationProvider);

        var client = new Client()
        {
            ContactDetails = new []
            {
                new ContactDetails()
                {
                    Address= "Old"
                }
            }
        };

        var clientDto = new ClientDto()
        {
            ContactDetails = new []
            {
                new ContactDetailsDto()
                {
                    Address = "New"
                }
            }
        };

        mapper.Map(clientDto,client);
        Console.WriteLine(client.ContactDetails.First().Address);
    }
}

public class Client
{
    public ContactDetails[] ContactDetails { get; set; }
}

public class ContactDetails
{
    public string Address { get; set; }
}

public class ClientDto
{
    public ContactDetailsDto[] ContactDetails { get; set; }
}

public class ContactDetailsDto
{
    public string Address { get; set; }
}

public class ClientMapperProfile : Profile
{
    public ClientMapperProfile()
    {
        CreateMap<ClientDto, Client>();

        CreateMap<ContactDetailsDto, ContactDetails>()
            .ForMember(c => c.Address, opt => opt.Ignore());
    }
}

问题原因

核心问题出在AutoMapper对数组类型属性的默认映射逻辑:
AutoMapper处理数组时,默认会创建一个全新的数组实例,替换掉目标对象中原有的数组。也就是说,client.ContactDetails会被替换成新的ContactDetails[],这个新数组里的ContactDetails对象是全新生成的——虽然你对Address设置了Ignore(),但新对象的Address本身就是默认的null,最终输出自然是null,而非原有的“Old”。

解决方案

方案1:配置集合映射保留目标实例

修改ClientDto到Client的映射,使用UseDestinationValue()让AutoMapper复用目标端原有的数组实例,只对数组内的元素进行属性映射:

public class ClientMapperProfile : Profile
{
    public ClientMapperProfile()
    {
        CreateMap<ClientDto, Client>()
            .ForMember(dest => dest.ContactDetails, opt => opt.UseDestinationValue());

        CreateMap<ContactDetailsDto, ContactDetails>()
            .ForMember(c => c.Address, opt => opt.Ignore());
    }
}

方案2:改用List替代数组

AutoMapper对List<T>的默认处理逻辑是复用目标集合实例,仅更新集合内的元素属性。将代码中的数组类型替换为List即可:

// 修改Client类
public class Client
{
    public List<ContactDetails> ContactDetails { get; set; }
}

// 修改ClientDto类
public class ClientDto
{
    public List<ContactDetailsDto> ContactDetails { get; set; }
}

// 实例化时对应修改为List
var client = new Client()
{
    ContactDetails = new List<ContactDetails>()
    {
        new ContactDetails() { Address= "Old" }
    }
};

var clientDto = new ClientDto()
{
    ContactDetails = new List<ContactDetailsDto>()
    {
        new ContactDetailsDto() { Address = "New" }
    }
};

验证效果

采用任意一种方案修改后,运行代码,client.ContactDetails.First().Address会输出预期的“Old”。

内容的提问来源于stack exchange,提问作者Thiago

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 10:11:35