AutoMapper中PropertyMap的SourceMember属性为空问题排查咨询
问题原因
AutoMapper的PropertyMap.SourceMember仅在直接成员到成员的默认映射场景下会自动填充,只要你使用了MapFrom lambda、自定义值解析器、类型转换配置,该属性就会为null。你原有代码返回空通常有两个核心原因:
- 如果你使用的是接收
Func<TSource, TMember>委托的MapFrom重载、自定义IValueResolver、或者ConvertUsing做映射,CustomMapExpression属性本身就为null,因为这类配置没有保存表达式树信息,只保留了编译后的委托 - 就算你用的是表达式树版本的
MapFrom重载,如果lambda内存在类型转换、空值合并等操作,CustomMapExpression.Body不是直接的MemberExpression,也会导致你拿不到预期的成员名
解决方法
第一步:优先使用表达式树版本的MapFrom配置映射
如果要能从PropertyMap中解析出源成员名,映射配置时要使用带表达式树参数的MapFrom重载,不要用委托重载、也尽量避免复杂的lambda逻辑:
// 正确:用表达式树重载,会保留表达式信息 CreateMap<Source, Dest>().ForMember(d => d.UserName, opt => opt.MapFrom(s => s.Name)); // 错误:用委托重载,不会保存表达式信息,CustomMapExpression为null CreateMap<Source, Dest>().ForMember(d => d.UserName, opt => opt.MapFrom(s => { return s.Name; }));
第二步:改进GetSourceName方法,处理表达式树的嵌套情况
需要递归解析表达式树,跳过类型转换、装箱等包装节点,提取最终的成员名:
private string GetSourceName(PropertyMap propertyMap) { // 先尝试拿直接映射的源成员名 var sourceName = propertyMap.SourceMember?.Name; if (!string.IsNullOrEmpty(sourceName)) return sourceName; // 处理MapFrom表达式的情况 var expression = propertyMap.CustomMapExpression; if (expression == null) return null; var body = expression.Body; // 去掉转换、装箱等UnaryExpression包装 while (body.NodeType is ExpressionType.Convert or ExpressionType.ConvertChecked) { body = ((UnaryExpression)body).Operand; } // 如果是成员访问,直接返回成员名 if (body is MemberExpression memberExp) { return memberExp.Member.Name; } // 其他复杂表达式场景,返回原始toString结果 return body.ToString(); }
特殊场景说明
如果你确实需要用自定义值解析器做映射,这类场景下AutoMapper没有保存任何源成员相关的表达式信息,无法通过PropertyMap的现有属性提取到源成员名,你可以在配置映射时通过MapFrom的表达式重载配合自定义方法,或者额外打标签存储源成员信息。
注:上述方法适配AutoMapper 9.x及以上版本,低版本的
PropertyMap属性名可能存在差异,可以对应调整。
内容的提问来源于stack exchange,提问作者paneerchilli
相关产品推荐
相关产品推荐

