Mapster 忽略成员映射完全指南:Ignore / IgnoreIf / IgnoreNullValues 与 AdaptIgnore 属性详解

发布时间:2026/9/18 16:52:59
Mapster 忽略成员映射完全指南:Ignore / IgnoreIf / IgnoreNullValues 与 AdaptIgnore 属性详解 Mapster 忽略成员映射完全指南Ignore / IgnoreIf / IgnoreNullValues 与 AdaptIgnore 属性详解【免费下载链接】MapsterA fast, fun and stimulating object to object Mapper项目地址: https://gitcode.com/GitHub_Trending/ma/MapsterMapster 默认会按名称自动映射源对象与目标对象的同名属性但在实际项目中我们常常需要跳过某些成员——例如业务上不参与拷贝的 Id、敏感字段、EF 导航属性或者只希望拷贝有值的属性。本文基于 Ignoring-members.md 展开系统讲解 Mapster 提供的六类忽略成员手段Ignore、IgnoreMember、IgnoreNonMapped、[AdaptIgnore]属性、IgnoreIf、IgnoreNullValues并结合 src/Mapster 源码说明每类手段的底层实现与适用场景。读完本文你将能根据按名称、按规则、按属性、按条件、按值五种维度精确控制映射行为。一、按名称忽略Ignore方法Mapster 默认会映射所有同名属性。当某个目标成员不希望在映射时被赋值可以直接用Ignore方法按目标成员名称跳过它TypeAdapterConfigTSource, TDestination .NewConfig() .Ignore(dest dest.Id);从源码看Ignore有两种重载形态字符串重载泛型TSetter扩展见 TypeAdapterSetter.cs逐个把成员名写入Settings.Ignore字典表达式重载见 TypeAdapterSetter.cs通过member.GetMemberPath()取出目标成员的路径字符串后同样写入Settings.Ignore。Settings.Ignore是一个IgnoreDictionary见 IgnoreDictionary.cs其值为IgnoreItem结构体携带Condition条件表达式与IsChildPath是否子路径两个字段。因此按名称忽略既支持dest dest.Id这种单成员表达式也支持params参数一次忽略多个成员TypeAdapterConfigTSource, TDestination .NewConfig() .Ignore(dest dest.Id, dest dest.CreatedAt);在编译映射时BaseClassAdapter.cs 中的ProcessIgnores会先通过destinationMember.ShouldMapMember(arg, MemberSide.Destination)检查成员是否允许映射再从arg.Settings.Ignore中按成员名取出IgnoreItem只要该条目存在且Condition null即无条件忽略该成员的赋值代码就不会被生成。与之配套Mapster 还提供了两个反向操作IgnoredRemove(params ExpressionFuncTDestination, object[] members)从忽略字典中移除指定成员TypeAdapterSetter.csIgnoredClear()清空当前配置上的全部忽略项TypeAdapterSetter.cs。典型使用场景在部分更新的 DTO 中主键与审计字段不应被前端数据覆盖可以先Ignore再通过显式Map单独赋值。二、基于规则的忽略IgnoreMember与IncludeMemberIgnore只能按目标成员名逐一指定而IgnoreMember可以基于成员信息类型、名称、访问修饰符、所属端等批量决定是否忽略适合处理整类成员都不映射的规则化需求TypeAdapterConfig.GlobalSettings.Default .IgnoreMember((member, side) !validTypes.Contains(member.Type));上面的例子会忽略所有类型不在validTypes白名单中的成员——典型用途是跳过 EF 导航属性等复杂类型。判定函数的入参为IMemberModel与MemberSidepublic interface IMemberModel { Type Type { get; } string Name { get; } object Info { get; } AccessModifier SetterModifier { get; } AccessModifier AccessModifier { get; } IEnumerableobject GetCustomAttributes(bool inherit); } public enum MemberSide { Source, Destination, }从源码看IgnoreMember将谓词包装后加入Settings.ShouldMapMember规则链谓词返回true时给出false判定禁止映射否则返回null表示不表态、交给后续规则TypeAdapterSetter.cs。这种返回bool?的设计使多个规则可以叠加返回null即跳过本条规则让更具体的规则或默认规则继续裁决。对称地IncludeMember在谓词返回true时给出true判定用于强制包含成员TypeAdapterSetter.cs。基于该机制可以演化出多种实用规则完整示例见 Rule-based-member-mapping.md// 只允许属性映射拒绝字段Info 可能是 PropertyInfo / FieldInfo / ParameterInfo TypeAdapterConfig.GlobalSettings.Default .IgnoreMember((member, side) member.Info is FieldInfo); // 只允许 System 命名空间下的类型 TypeAdapterConfig.GlobalSettings.Default .IgnoreMember((member, side) !member.Type.Namespace.StartsWith(System)); // 只映射带 [DataMember] 的成员 TypeAdapterConfig.GlobalSettings.Default .IncludeMember((member, side) member.GetCustomAttributes(true).OfTypeDataMemberAttribute().Any()); TypeAdapterConfig.GlobalSettings.Default .IgnoreMember((member, side) !member.GetCustomAttributes(true).OfTypeDataMemberAttribute().Any()); // 禁止非 public 的 setter 被映射Mapster 默认允许非 public setter TypeAdapterConfig.GlobalSettings.Default .IgnoreMember((member, side) side MemberSide.Destination member.SetterModifier ! AccessModifier.Public);IgnoreNonMapped只映射显式指定的成员IgnoreNonMapped是规则化忽略的强化形态开启后所有没有显式Map解析器的成员都会被忽略。例如只希望映射Id和Name两个成员TypeAdapterConfigTSource, TDestination .NewConfig() .Map(dest dest.Id, src src.Id) .Map(dest dest.Name, src src.Name) .IgnoreNonMapped(true);其底层实现在 BaseClassAdapter.cs 的IgnoreNonMapped方法中用LinqCompat.ExceptBy计算目标成员集合 − 已配置解析器的目标成员名集合得到所有未映射成员再逐个写入Settings.Ignore。同时BaseClassAdapter.cs 在解析 getter 时一旦开启IgnoreNonMapped就只从CustomResolvers自定义解析器中寻找来源不再使用默认的同名属性匹配。需要注意IgnoreNonMapped与RequireDestinationMemberSource的差异前者是未映射的成员保持默认值后者是在编译期直接抛错强制所有目标成员都有来源。在IgnoreNonMapped(true)开启时若想恢复某个成员可用Map显式指定或IgnoredRemove移除。三、通过特性忽略[AdaptIgnore]与IgnoreAttribute如果你不想在映射配置中逐一列举可以直接在模型类上打标public class Product { public string Id { get; set; } public string Name { get; set; } [AdaptIgnore] public decimal Price { get; set; } }[AdaptIgnore]定义在 AdaptIgnoreAttribute.cs可作用于字段与属性并支持指定生效方向Side[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public class AdaptIgnoreAttribute : Attribute { public MemberSide? Side { get; set; } // 无参构造双向忽略带 MemberSide 的构造仅忽略指定方向 }Side为空表示双向忽略否则只忽略Source作为源时或Destination作为目标时这一侧。对应规则ShouldMapMember.IgnoreAdaptIgnore定义在 ShouldMapMember.cs命中[AdaptIgnore]且方向匹配时返回false否则返回null交给后续规则。而IgnoreAttribute则针对自定义特性批量忽略——凡是携带指定特性如[JsonIgnore]、[Browsable(false)]的成员都跳过TypeAdapterConfigTSource, TDestination .NewConfig() .IgnoreAttribute(typeof(JsonIgnoreAttribute));其实现TypeAdapterSetter.cs遍历特性类型为每个类型追加一条规则member.HasCustomAttribute(type) ? (bool?)false : null。这与IncludeAttribute强制包含带某特性的成员TypeAdapterSetter.cs成对出现二者都复用ShouldMapMember规则链。更完整的特性化配置含[AdaptMember]、[AdaptWith]等见 Setting-by-attributes.md。四、按条件忽略IgnoreIfIgnore是无条件忽略而IgnoreIf允许在运行时根据源对象或目标对象的状态决定是否跳过某个成员TypeAdapterConfigTSource, TDestination .NewConfig() .IgnoreIf((src, dest) !string.IsNullOrEmpty(dest.Name), dest dest.Name);与带条件的Map的关键区别原文档明确强调Map(..., shouldMap)条件不满足时目标成员会被赋值为nullIgnoreIf条件满足时该成员的映射会被整体跳过即不生成任何赋值语句目标保持原有值。这在合并/部分更新场景中至关重要只有当前目标Name已有值时才会被源覆盖否则保持原样。IgnoreIf支持条件表达式 多个成员TypeAdapterConfigTSource, TDestination .NewConfig() .IgnoreIf((src, dest) src.IsDeleted, dest dest.Name, dest dest.Address);其底层实现TypeAdapterSetter.cs将条件表达式与成员名一起写入Settings.Ignore字典IgnoreItem(condition, false)。IgnoreDictionary.MergeIgnoreDictionary.cs还有一个值得注意的行为同一成员的多个IgnoreIf条件会被自动合并——先用已存在的条件应用到当前参数再用Expression.OrElse将新旧条件取或最终生成任一条件满足即跳过的组合条件。测试 WhenIgnoringConditionally.cs 中的IgnoreIf_Can_Be_Combined用例验证了这一行为对同一成员先后注册src.Name NotTestName与src.Name TestName两个条件后两个分支都会被忽略。该测试文件还覆盖了IgnoreIf(null, ...)无条件忽略、对 record 类型生效等边界情况WhenIgnoringConditionally.cs。五、按值忽略IgnoreNullValues默认情况下Mapster 会映射所有属性——即使源属性为null也会把null写入目标。当你希望从输入对象合并、只拷贝源中有值的属性时可以开启IgnoreNullValuesTypeAdapterConfigTSource, TDestination .NewConfig() .IgnoreNullValues(true);开启后映射生成的代码形态从直接赋值变为空值守卫赋值// ### 未开启 IgnoreNullValues // dest.Prop1 convert(src.Prop1); // dest.Prop2 convert(src.Prop2); // ### 开启 IgnoreNullValues // if (src.Prop1 ! null) // dest.Prop1 convert(src.Prop1); // if (src.Prop2 ! null) // dest.Prop2 convert(src.Prop2);上述注释直接来自 ClassAdapter.cs 的CreateBlockExpression实现。具体生成逻辑见 ClassAdapter.cs当IgnoreNullValues true、源成员 getter 可空member.Getter.CanBeNull()且目标 setter 可用时会把adapt表达式包进if (src.PropX ! null)守卫若守卫内是x null ? ... : ...形式的条件表达式还会把ifFalse分支提取出来避免冗余。这一点与 Shallow-merge.md 描述的浅合并场景相辅相成IgnoreNullValues与ShallowCopyForSameType分别从值层面与对象层面控制合并粒度。需要注意的是IgnoreNullValues、带条件的Ignore等不支持投影Projection。在 ClassAdapter.cs 中MapType.Projection会直接返回true跳过这些优化因为 LINQ 投影表达式树无法携带 if 守卫语义投影请改用ProjectToType配合其他筛选手段。六、小结五种忽略手段的选型对照手段忽略粒度判定时机典型场景Ignore(dest ...)按目标成员名编译期确定单个/少数成员不参与映射如主键、审计字段IgnoreMember(predicate)按成员元数据规则编译期确定按类型、命名空间、访问级别、特性批量过滤如跳过 EF 导航属性IgnoreNonMapped(true)未显式Map的成员编译期确定白名单式映射只映射显式声明的成员[AdaptIgnore]/IgnoreAttribute按成员特性编译期确定模型类上直接打标或统一忽略携带某自定义特性的成员IgnoreIf(condition, ...)按运行期条件运行期求值合并/部分更新条件满足时整体跳过赋值IgnoreNullValues(true)按源值是否为 null运行期求值输入合并只拷贝源中有值的属性需要特别强调的是运行期与编译期的差别前四种在映射表达式编译时就被写死不产生额外判断开销后两种则在生成的表达式中保留运行期条件IgnoreIf的条件表达式、IgnoreNullValues的 null 守卫语义更强但会略微增加生成代码的复杂度。所有上述 API 均以扩展方法形式定义在 TypeAdapterSetter.cs且都经过CheckCompiled()守卫——配置一旦被编译首次调用Adapt/BuildAdapter之后再尝试修改配置会抛出异常因此请务必在应用启动阶段完成忽略规则注册。若使用双向映射TwoWays对应的Ignore、IgnoreMember、IgnoreNonMapped、IgnoreNullValues等 API 也会自动作用于反向映射TypeAdapterSetter.cs可实现一次配置、双向生效。延伸阅读Rule-based-member-mapping.mdIMemberModel/MemberSide谓词的更多规则示例Setting-by-attributes.md[AdaptIgnore]之外的其他映射特性Shallow-merge.md与IgnoreNullValues配套的浅合并场景TypeAdapterSetter.cs本文所有忽略 API 的源码实现BaseClassAdapter.csProcessIgnores与IgnoreNonMapped的编译期处理逻辑WhenIgnoringConditionally.csIgnoreIf条件合并与边界行为的测试用例【免费下载链接】MapsterA fast, fun and stimulating object to object Mapper项目地址: https://gitcode.com/GitHub_Trending/ma/Mapster创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询