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

如何在AutoMapper更新时保留集合对象的未映射属性?

问题:AutoMapper更新时保留集合对象的自定义属性

场景说明

我有一个源对象和目标对象,两者都包含Elements集合。使用AutoMapper将源对象映射到目标对象后,我给目标对象独有的属性ItemName、ItemNumber赋值,同时给AssetElementDto集合内对象的Text属性赋值。之后调用mapper.Map(source_update, destination);更新目标对象。

遇到的问题

运行代码后,ItemName和ItemNumber的信息在更新后得以保留,但AssetElementDto的Text信息丢失了,如何让该属性也保留?

示例代码

using AutoMapper;
using System.Runtime.InteropServices;

public class Program
{
    static void Main(string[] arg)
    {
        var config = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<Source, Destination>().PreserveReferences();
            cfg.CreateMap<AssetElement, AssetElementDto>().PreserveReferences();
        });
        var mapper = new Mapper(config);

        var source = new Source()
        {
            Name = "Sinonis",
            Id = new Random().Next(),
            Elements = new List<AssetElement>
            {
                new(){ Id = 1},
                new(){ Id = 2}
            }
        };

        var destination = mapper.Map<Destination>(source);
        destination.ItemNumber = 42;
        destination.Elements.ForEach(e => e.Text ="Wow");

        destination.ItemName = "NPC21";

        var source_update = new Source()
        {
            Name = "Nindalf",
            Id = new Random().Next(),
            Elements = new List<AssetElement>
            {
                new(){ Id = 3},
                new(){ Id = 4}
            }
        };

        Console.WriteLine($"Before update is: {destination.Name} {destination.Id} {destination.ItemNumber} {destination.ItemName}");
        destination.Elements.ForEach(e => Console.WriteLine($" {e.Id} {e.Text}"));

        mapper.Map(source_update, destination);

        Console.WriteLine($"After update is : {destination.Name} {destination.Id} {destination.ItemNumber} {destination.ItemName}");
        destination.Elements.ForEach(e => Console.WriteLine($" {e.Id} {e.Text}"));
    }
}

#region Source

public class Source
{
    public string Name;
    public int Id;

    public List<AssetElement> Elements;

}

public class AssetElement
{
    public int Id;
}

#endregion

#region Destination

public class Destination
{
    public string Name;
    public int Id;

    public List<AssetElementDto> Elements;

    public int ItemNumber;
    public string ItemName;
}

public class AssetElementDto
{
    public string Text;
    public int Id;
}

#endregion

控制台输出

Before update is: Sinonis 1643275093 42 NPC21
 1 Wow
 2 Wow
After update is : Nindalf 75522068 42 NPC21
 3 null
 4 null

可以看到Wow在更新后未被保留。

解决方案

要保留Text属性,需要配置AutoMapper对集合执行合并更新而非完全替换,同时指定集合对象的匹配规则,让AutoMapper找到已存在的目标对象并更新,而非创建新对象。具体实现如下:

修改Mapper配置

var config = new MapperConfiguration(cfg =>
{
    cfg.AddCollectionMappers(); // 启用AutoMapper内置集合映射器
    cfg.CreateMap<Source, Destination>().PreserveReferences();
    cfg.CreateMap<AssetElement, AssetElementDto>()
        .EqualityComparison((src, dest) => src.Id == dest.Id) // 用Id作为集合元素的匹配依据
        .ForMember(dest => dest.Text, opt => opt.UseDestinationValue()); // 保留目标对象的Text属性值
});

原理说明

  • UseDestinationValue():告诉AutoMapper在更新时,目标对象的Text属性保持现有值,不被源对象(无Text属性,默认会设为null)覆盖。
  • EqualityComparison:指定集合元素的匹配规则,让AutoMapper能匹配源和目标集合中Id相同的元素,执行属性更新而非直接替换整个集合。
  • AddCollectionMappers():启用AutoMapper的集合合并逻辑,避免直接替换目标集合。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 02:20:27