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

如何使用AutoMapper将PersonEntity列表结合NameMode枚举映射为PersonDto列表?

如何使用AutoMapper将PersonEntity列表结合NameMode枚举映射为PersonDto列表?

我明白你遇到的问题了——你已经搞定了单个(PersonEntity, NameMode)元组到PersonDto的映射,但批量处理列表的时候踩了两个坑:直接传(List<PersonEntity>, NameMode)给Map方法,AutoMapper找不到对应的映射配置;用ProjectTo的时候又碰到了表达式树不支持元组字面量的语法错误。

下面给你几个可行的解决方案,你可以根据自己的场景来选:

方案一:用自定义包装类替代元组(适合EF查询投影场景)

C#的表达式树确实不支持元组字面量,但它能解析自定义类的实例创建。我们先搞一个包装类,把PersonEntity和NameMode包起来:

public class PersonWithNameMode
{
    public PersonEntity Person { get; set; }
    public NameMode Mode { get; set; }
}

然后修改你的AutoMapper映射配置,把源类型换成这个包装类:

CreateMap<PersonWithNameMode, PersonDto>()
    .ForMember(dest => dest.Name, opt => opt.MapFrom<NameCustomResolver>());

记得调整你的NameCustomResolver解析器,现在源是PersonWithNameMode,所以要从source.Person里拿姓名,从source.Mode里拿枚举值。

之后在查询投影的时候就可以正常写了:

var result = source.AsQueryable()
    .Select(p => new PersonWithNameMode { Person = p, Mode = NameMode.full })
    .ProjectTo<PersonDto>(mapper.ConfigurationProvider);

这样EF就能正确解析表达式树,完成投影映射。

方案二:内存中逐个映射(适合数据已在内存的场景)

如果你的source列表已经是内存中的数据(不是EF的IQueryable),那最简单的方式就是遍历每个元素,和枚举组合成元组后逐个映射:

List<PersonDto> destination = source
    .Select(p => mapper.Map<PersonDto>((p, NameMode.full)))
    .ToList();

这种方式完全不用修改你原来的元组映射配置,直接复用已有的规则,简单粗暴又有效。

方案三:利用AutoMapper上下文传递枚举(最灵活的方案)

其实我们可以不用元组或者包装类,直接把NameMode放到AutoMapper的映射上下文里,让解析器从上下文里取枚举值。

先修改映射配置,把源换回PersonEntity:

// 如果你用内联映射逻辑
CreateMap<PersonEntity, PersonDto>()
    .ForMember(dest => dest.Name, opt => opt.MapFrom((src, _, __, context) => 
    {
        var mode = (NameMode)context.Items["NameMode"];
        return mode == NameMode.full ? $"{src.FirstName} {src.LastName}" : src.FirstName;
    }));

// 如果你还是想用自定义解析器
public class NameCustomResolver : IValueResolver<PersonEntity, PersonDto, string>
{
    public string Resolve(PersonEntity source, PersonDto destination, string destMember, ResolutionContext context)
    {
        var mode = (NameMode)context.Items["NameMode"];
        return mode == NameMode.full ? $"{source.FirstName} {source.LastName}" : source.FirstName;
    }
}

// 对应的映射配置
CreateMap<PersonEntity, PersonDto>()
    .ForMember(dest => dest.Name, opt => opt.MapFrom<NameCustomResolver>());

然后映射列表的时候,通过Map的重载传递上下文参数:

List<PersonDto> destination = mapper.Map<List<PersonDto>>(source, opt => 
{
    opt.Items["NameMode"] = NameMode.full;
});

这种方式不需要额外定义类,配置更简洁,而且你可以在不同的映射场景中传递不同的NameMode值,灵活性拉满。


备注:内容来源于stack exchange,提问作者maces13

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 14:09:37