AutoMapper复合内部类列表属性映射赋值报错解决方法
报错原因
你遇到的错误核心来自两个配置误区:
- AutoMapper的
ForMember/ForPath方法仅支持纯成员访问的lambda表达式,不允许在路径中调用.First()这类LINQ方法,因此直接写dest => dest.InnerDestinations.First().Description会触发参数校验错误。 IncludeMembers的作用是将嵌套对象的属性扁平化映射到根目标对象的同级属性,无法用来生成、映射子列表属性,属于API误用。同时你试图直接操作列表的第一个元素时,目标列表本身尚未初始化,即使跳过表达式校验也会触发空引用异常。
正确配置方式
列表类型的属性映射不要尝试通过路径访问单个列表元素,直接在根对象映射规则中手动指定列表的生成逻辑即可,参考如下可运行的配置:
public void ComplexAssignmentData() { try { var config = new MapperConfiguration(cfg => { // 配置列表元素类型的基础映射(需要复用映射规则时可保留,也可以直接手动投影生成对象) cfg.CreateMap<OtherInnerSource, InnerDestination>(); cfg.CreateMap<Source, Destination>() // 手动映射InnerDestinations列表属性 .ForMember(dest => dest.InnerDestinations, opt => opt.MapFrom(src => { var destList = new List<InnerDestination>(); // 场景1:如果要把InnerSource的Description合并到每一个OtherInnerSource映射的目标项,使用以下循环逻辑 foreach (var otherSource in src.OtherInnerSources) { destList.Add(new InnerDestination { Description = src.InnerSource.Description, Title = otherSource.Title }); } // 场景2:如果要把InnerSource单独映射为一个列表项,和OtherInnerSources映射的项并列,注释上面的循环,放开以下代码 // destList.Add(new InnerDestination { Description = src.InnerSource.Description }); // destList.AddRange(src.OtherInnerSources.Select(s => new InnerDestination // { // Title = s.Title, // Description = s.Description // })); return destList; })); }); var source = new Source { Name = "name", InnerSource = new InnerSource { Description = "description" }, OtherInnerSources = { new OtherInnerSource { Title = "title" } } }; config.AssertConfigurationIsValid(); var mapper = config.CreateMapper(); var destination = mapper.Map<Destination>(source); } catch (Exception ex) { // 自定义异常处理逻辑 } }
补充说明
- 上述写法不需要额外配置
InnerSource/OtherInnerSource到Destination的映射,避免了无效的扁平化配置。 - 映射执行时会自动完成列表初始化,不会出现空引用问题,同时支持源列表包含多个元素的场景,不会只映射第一个元素。
- 你可以根据实际业务需求,在
MapFrom的逻辑里调整列表元素的合并规则,不需要受AutoMapper默认映射规则的限制。
内容的提问来源于stack exchange,提问作者vasu
相关产品推荐
相关产品推荐

