AutoMapper 创建嵌套对象映射(原创)
之前在做DTO转换时,用到AutoMapper。但DTO的层次太深了,无奈官方没针对嵌套类型提供好的解决方案,于是自己实现了一下:
思路:采用递归和反射很好的避免手工创建嵌套对象的映射。
第一个版本,已经提交到:https://github.com/AutoMapper/AutoMapper/wiki/Nested-mappings

1 /// <summary> 2 /// 递归创建类型间的映射关系 (Recursively create mappings between types) 3 ///created by cqwang 4 /// </summary> 5 /// <param name="sourceType"></param> 6 /// <param name="destinationType"></param> 7 public static void CreateNestedMappers(Type sourceType, Type destinationType) 8 { 9 PropertyInfo[] sourceProperties = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance); 10 PropertyInfo[] destinationProperties = destinationType.GetProperties(BindingFlags.Public | BindingFlags.Instance); 11 foreach (var destinationProperty in destinationProperties) 12 { 13 Type destinationPropertyType = destinationProperty.PropertyType; 14 if (Filter(destinationPropertyType)) 15 continue; 16 17 PropertyInfo sourceProperty = sourceProperties.FirstOrDefault(prop => NameMatches(prop.Name, destinationProperty.Name)); 18 if (sourceProperty == null) 19 continue; 20 21 Type sourcePropertyType=sourceProperty.PropertyType; 22 if (destinationPropertyType.IsGenericType) 23 { 24 Type destinationGenericType = destinationPropertyType.GetGenericArguments()[0]; 25 if (Filter(destinationGenericType)) 26 continue; 27 28 Type sourceGenericType = sourcePropertyType.GetGenericArguments()[0]; 29 CreateMappers(sourceGenericType, destinationGenericType); 30 } 31 else 32 { 33 CreateMappers(sourcePropertyType, destinationPropertyType); 34 } 35 } 36 37 Mapper.CreateMap(sourceType, destinationType); 38 } 39 40 /// <summary> 41 /// 过滤 (Filter) 42 /// </summary> 43 /// <param name="type"></param> 44 /// <returns></returns> 45 static bool Filter(Type type) 46 { 47 return type.IsPrimitive || NoPrimitiveTypes.Contains(type.Name); 48 } 49 50 static readonly HashSet<string> NoPrimitiveTypes = new HashSet<string>() { "String", "DateTime", "Decimal" }; 51 52 private static bool NameMatches(string memberName, string nameToMatch) 53 { 54 return String.Compare(memberName, nameToMatch, StringComparison.OrdinalIgnoreCase) == 0; 55 }
后来自测中发现,要过滤的一些结构体可能很多,比较麻烦,所以自己又完善了下,有了第二个版本
第二个版本在公司内的一些服务中已经使用并上线,挺好。因为并未涉及到公司内的任何业务信息,只是简单的思路和实现,所以这里贴出来给大家分享一下。
所有代码为原创,转载请注明出处。
其实,本没有路,走过去,便是路。
顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构