之前在做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 }
后來自測中發現,要過濾的一些結構體可能很多,比較麻煩,所以自己又完善了下,有了第二個版本
第二個版本在公司內的一些服務中已經使用並上線,挺好。因為並未涉及到公司內的任何業務信息,只是簡單的思路和實現,所以這里貼出來給大家分享一下。
所有代碼為原創,轉載請注明出處。
其實,本沒有路,走過去,便是路。