C#中如何使用AutoMapper动态将指定外的对象属性设置为null
AutoMapper 实现方案
方案1:动态构建映射配置(适合白名单变化频率极低的场景)
如果你的属性白名单很长时间才会变化一次,可以每次白名单更新时构建一次映射配置,代码如下:
// 你的动态白名单属性数组 string[] allowedProperties = new [] { "属性1", "属性2", "属性10" }; var mapperConfig = new MapperConfiguration(cfg => { // 泛型参数替换为你实际的实体类型 cfg.CreateMap<YourEntity, YourEntity>() .ForAllMembers(opt => { // 属性在白名单内则保留原值,否则赋值为null opt.MapFrom(src => allowedProperties.Contains(opt.DestinationMember.Name) ? opt.DestinationMember.GetValue(src) : null ); }); }); var mapper = mapperConfig.CreateMapper(); // 直接映射整个列表,和原代码一致修改原对象的话使用以下重载 mapper.Map(ListItems, ListItems); // 如果需要返回新列表不修改原数据,使用 var result = mapper.Map<List<YourEntity>>(ListItems);
方案2:复用全局配置+上下文传参(适合白名单每次调用都可能变化的场景)
如果每次调用时白名单都可能不同,建议全局只初始化一次映射配置,通过上下文参数动态传递白名单,避免频繁构建配置带来的性能损耗:
// 全局仅初始化一次映射配置 var globalMapperConfig = new MapperConfiguration(cfg => { cfg.CreateMap<YourEntity, YourEntity>() .ForAllMembers(opt => { opt.MapFrom((src, dest, member, context) => { // 从映射上下文取出白名单 var allowedProps = context.Items["AllowedProps"] as HashSet<string>; // 白名单不存在或当前属性在白名单内,保留原值 if (allowedProps == null || allowedProps.Contains(opt.DestinationMember.Name)) { return opt.DestinationMember.GetValue(src); } // 不在白名单则返回null return null; }); }); }); // 全局复用同一个mapper实例 var globalMapper = globalMapperConfig.CreateMapper();
每次调用时传入当前白名单即可:
// 你的动态白名单,转HashSet优化查询性能 var currentAllowedProps = new HashSet<string>(你的属性名称数组); // 映射时传入白名单到上下文,直接修改原列表 globalMapper.Map(ListItems, ListItems, opt => { opt.Items["AllowedProps"] = currentAllowedProps; });
注意事项
- 如果实体中包含
int、DateTime等不可空值类型属性,需先将其声明为对应的可空类型(如int?、DateTime?),否则赋值null会抛出运行时异常。 - 该实现性能远高于手写反射遍历的实现,AutoMapper内部已经对反射调用做了缓存优化,列表量级越大优势越明显。
内容的提问来源于stack exchange,提问作者gorak
相关产品推荐
相关产品推荐

