咨询AutoMapper Issue #3926中Nullable<T>参数异常的解决方案
问题描述
AutoMapper Issue #3962已被关闭并锁定,未给出任何解释或解决方案(实际上所有AutoMapper的Issue都被如此处理,维护者引导用户到社区求助)。
问题核心:IMemberConfigurationExpression.Condition接收的Func<TSrc, TDest, object, bool>委托,第三个参数为当前访问的源成员值。示例代码如下:
public static class IMappingExpressionExtensions { public static void Coalesce<Src, Dst>(this IMappingExpression<Src, Dst> exp) { exp.ForAllMembers(cfg => cfg.Condition((src, dst, srcMember) => srcMember != null)); } }
当源成员为引用类型且值为null时,srcMember符合预期为null;但当源成员为无值的Nullable<T>类型时,srcMember意外返回default(T)而非null,导致条件判断失效。
可行解决方案
以下是两种可靠的解决思路:
1. 使用带上下文的Condition重载
AutoMapper提供了包含映射上下文的Condition重载,可通过上下文获取成员元数据,判断是否为Nullable<T>类型并检查实际值:
public static void Coalesce<Src, Dst>(this IMappingExpression<Src, Dst> exp) { exp.ForAllMembers(cfg => { cfg.Condition((src, dst, context) => { var sourceMember = context.MemberMap.SourceMember; if (sourceMember == null) return true; // 检查成员是否为Nullable<T>类型 var underlyingType = Nullable.GetUnderlyingType(sourceMember.PropertyType); if (underlyingType != null) { var value = sourceMember.GetValue(src); return value != null; // Nullable<T>无值时GetValue返回null } // 处理引用类型和普通值类型 var srcMemberValue = context.MemberMap.GetSourceValue(src); return srcMemberValue != null; }); }); }
2. 直接通过反射检查源成员值
如果不想依赖AutoMapper上下文,可直接通过反射获取源成员的实际值,区分Nullable<T>无值的情况:
public static void Coalesce<Src, Dst>(this IMappingExpression<Src, Dst> exp) { exp.ForAllMembers(cfg => { cfg.Condition((src, dst, srcMember) => { var sourceMember = cfg.MemberMap.SourceMember; if (sourceMember == null) return true; var propertyType = sourceMember.PropertyType; // 判断是否为Nullable<T>类型 if (Nullable.GetUnderlyingType(propertyType) != null) { var value = sourceMember.GetValue(src); return value != null; } // 其他情况沿用原判断逻辑 return srcMember != null; }); }); }
两种方法都能正确识别Nullable<T>无值的场景,避免将default(T)误判为非null值,实现原Coalesce方法的预期效果。
内容的提问来源于stack exchange,提问作者Kevin Krumwiede
相关产品推荐
相关产品推荐

