如何在Mapster中基于成员值忽略属性并更新现有对象?
使用Mapster实现补丁式对象映射:自定义属性忽略规则
一、通过IgnoreMember实现自定义忽略逻辑
Mapster的IgnoreMember方法接收MemberSettingContext类型的参数,通过它可以获取源对象实例、当前成员的元数据,进而拿到属性值并判断是否忽略。
假设你的validMembers函数逻辑是“返回false则忽略成员”,配置方式如下:
TypeAdapterConfig<Source, Destination>.NewConfig() .IgnoreMember(ctx => { // 反射获取源对象当前成员的实际值 var memberValue = ctx.Source.GetType().GetProperty(ctx.Member.Name)?.GetValue(ctx.Source); // 传入自定义判断函数,返回true时忽略该成员 return !validMembers(memberValue, ctx.Member.Type); }) .Compile();
MemberSettingContext的关键属性:
Source: 源对象的实例,用于读取当前成员的真实值Member: 当前成员的元数据(包含Name、Type等信息)Destination: 目标对象实例(补丁场景下可用于对比已有值)
二、其他实现方案
1. 临时配置(单次映射)
如果仅需在单次补丁更新中应用规则,可直接在Adapt调用时传入临时配置:
source.Adapt(existingDestination, config => config .IgnoreMember(ctx => { var value = ctx.Source.GetType().GetProperty(ctx.Member.Name)?.GetValue(ctx.Source); return !validMembers(value, ctx.Member.Type); }) );
2. 全局自定义匹配器
若规则需要全局复用,可实现IMemberMatcher接口并注册到全局配置:
public class CustomIgnoredMemberMatcher : IMemberMatcher { public bool Match(MemberMatcherContext ctx) { var sourceValue = ctx.Source.GetType().GetProperty(ctx.SourceMember.Name)?.GetValue(ctx.Source); // 返回true表示该成员参与映射,false则忽略 return validMembers(sourceValue, ctx.SourceMember.Type); } } // 全局注册 TypeAdapterConfig.GlobalSettings.Matchers.Add(new CustomIgnoredMemberMatcher());
3. 单个属性的条件映射
针对特定属性单独设置规则,适合规则仅作用于少数属性的场景:
TypeAdapterConfig<Source, Destination>.NewConfig() .Map(dest => dest.TargetProperty, src => src.SourceProperty) .Condition((src, dest) => validMembers(src.SourceProperty, typeof(YourPropertyType))) .Compile();
三、补丁更新的核心要点
执行补丁式更新时,务必使用Adapt的重载方法传入已存在的目标对象,避免创建新对象覆盖原有数据:
// 正确:更新现有目标对象 source.Adapt(existingDestination, config => { /* 忽略规则配置 */ }); // 错误:创建新对象,无法实现补丁更新 var newDestination = source.Adapt<Destination>(config => { /* 忽略规则配置 */ });
内容的提问来源于stack exchange,提问作者M.Hassan
相关产品推荐
相关产品推荐

