Model ViewModel AutoMapper


先说说DTO

DTO是个什么东东?
DTO(Data Transfer Object)就是数据传输对象,说白了就是一个对象,只不过里边全是数据而已。
为什么要用DTO?
1、DTO更注重数据,对领域对象进行合理封装,从而不会将领域对象的行为过分暴露给表现层
2、DTO是面向UI的需求而设计的,而领域模型是面向业务而设计的。因此DTO更适合于和表现层的交互,通过DTO我们实现了表现层与领域Model之间的解耦,因此改动领域Model不会影响UI层
3、DTO说白了就是数据而已,不包含任何的业务逻辑,属于瘦身型的对象,使用时可以根据不同的UI需求进行灵活的运用

AutoMapper

现在我们既然知道了使用DTO的好处,那么我们肯定也想马上使用它,但是这里会牵扯一个问题:怎样实现DTO和领域Model之间的转换?
有两个思路,我们要么自己写转换代码,要么使用工具。不过就应用而言,我还是觉得用工具比较简单快捷,那就使用工具吧。其实这样的转换工具很多,不过我还是决定使用AutoMapper,因为它足够轻量级,而且也非常流行,国外的大牛们都使用它。使用AutoMapper可以很方便的实现DTO和领域Model之间的转换,它是一个强大的Object-Object Mapping工具。

一、如何添加AutoMapper到项目中?

在vs中使用打开工具-库程序包管理器-程序包管理控制平台,输入“Install-Package AutoMapper”命令,就可以把AutoMapper添加到项目中了~

二、举例说明

例子1:(两个类型之间的映射)

AddressDto到Address的映射,AddressDto的字段CountryName要对应Address的字段Country:

  1. Mapper.CreateMap<AddressDto, Address>();
  2. AddressDto dto = new AddressDto
  3. {
  4. Country = "China",
  5. City = "ShangHai",
  6. Street = "JinZhong Street"
  7. };
  8. Address address = Mapper.Map<AddressDto,Address>(Dto);

例子2:(两个映射的对象有部分字段名称不一样)

  1. Mapper.CreateMap<AddressDto, Address>(). ForMember(d => d.Country, opt => opt.MapFrom(s => s.CountryName));

例子3:(列表类型之间的映射)

源类型List

,目标类型List

  1. AutoMapper.Mapper.CreateMap< Address, AddressDto >();
  2. var addressDtoList = AutoMapper.Mapper.Map<List< Address >, List< AddressDto >>( addressList);

例子4:(映射在增改查中的应用)

  1. public class ProductBll
  2. {
  3. Public IProductRepository productRepository{ set; get; }
  4. public ProductDTO CreateProduct(ProductDTO productDTO)
  5. {
  6. Mapper.CreateMap<ProductDTO, Product>();
  7. Product product = Mapper.Map<ProductDTO, Product>(productDTO);
  8. productRepository.AddProduct(product);
  9. return productDTO;
  10. }
  11. public List<ProductDTO> GetProduct()
  12. {
  13. Mapper.CreateMap<Product, ProductDTO>();
  14. List<ProductDTO> arr = new List<ProductDTO>();
  15. productRepository.GetProduct().ForEach(i =>
  16. {
  17. arr.Add(Mapper.Map<Product, ProductDTO>(i));
  18. });
  19. return arr;
  20. }
  21. public ProductDTO ModifyProduct(ProductDTO productDTO)
  22. {
  23. Mapper.CreateMap<ProductDTO, Product>();
  24. Product product = Mapper.Map<ProductDTO, Product>(productDTO);
  25. productRepository.ModifyProduct(product);
  26. return productDTO;
  27. }
  28. }

吃过上面的栗子,你觉得怎么样呢?如果想继续吃,那就去查看AutoMapper的具体API文档吧!倘若在项目中真正要用的时候,我觉得还是应该对AutoMapper的方法进行一些整理,最好能够封装一下,这里我通过扩展方法的形式将其封装为AutoMapperHelper,这样以后使用AutoMapper就变的SO EASY了~

  1. public class ProductBll
  2. {
  3. Public IProductRepository productRepository{ set; get; }
  4. public ProductDTO CreateProduct(ProductDTO productDTO)
  5. {
  6. Mapper.CreateMap<ProductDTO, Product>();
  7. Product product = Mapper.Map<ProductDTO, Product>(productDTO);
  8. productRepository.AddProduct(product);
  9. return productDTO;
  10. }
  11. public List<ProductDTO> GetProduct()
  12. {
  13. Mapper.CreateMap<Product, ProductDTO>();
  14. List<ProductDTO> arr = new List<ProductDTO>();
  15. productRepository.GetProduct().ForEach(i =>
  16. {
  17. arr.Add(Mapper.Map<Product, ProductDTO>(i));
  18. });
  19. return arr;
  20. }
  21. public ProductDTO ModifyProduct(ProductDTO productDTO)
  22. {
  23. Mapper.CreateMap<ProductDTO, Product>();
  24. Product product = Mapper.Map<ProductDTO, Product>(productDTO);
  25. productRepository.ModifyProduct(product);
  26. return productDTO;
  27. }
  28. }
  29. 复制代码
  30. 三、让AutoMapper使用变得简单
  31. 吃过上面的栗子,你觉得怎么样呢?如果想继续吃,那就去查看AutoMapper的具体API文档吧!倘若在项目中真正要用的时候,我觉得还是应该对AutoMapper的方法进行一些整理,最好能够封装一下,这里我通过扩展方法的形式将其封装为AutoMapperHelper,这样以后使用AutoMapper就变的SO EASY了~
  32. 复制代码
  33. using System.Collections;
  34. using System.Collections.Generic;
  35. using System.Data;
  36. using AutoMapper;
  37. namespace Infrastructure.Utility
  38. {
  39. /// <summary>
  40. /// AutoMapper扩展帮助类
  41. /// </summary>
  42. public static class AutoMapperHelper
  43. {
  44. /// <summary>
  45. /// 类型映射
  46. /// </summary>
  47. public static T MapTo<T>(this object obj)
  48. {
  49. if (obj == null) return default(T);
  50. Mapper.CreateMap(obj.GetType(), typeof(T));
  51. return Mapper.Map<T>(obj);
  52. }
  53. /// <summary>
  54. /// 集合列表类型映射
  55. /// </summary>
  56. public static List<TDestination> MapToList<TDestination>(this IEnumerable source)
  57. {
  58. foreach (var first in source)
  59. {
  60. var type = first.GetType();
  61. Mapper.CreateMap(type, typeof(TDestination));
  62. break;
  63. }
  64. return Mapper.Map<List<TDestination>>(source);
  65. }
  66. /// <summary>
  67. /// 集合列表类型映射
  68. /// </summary>
  69. public static List<TDestination> MapToList<TSource, TDestination>(this IEnumerable<TSource> source)
  70. {
  71. //IEnumerable<T> 类型需要创建元素的映射
  72. Mapper.CreateMap<TSource, TDestination>();
  73. return Mapper.Map<List<TDestination>>(source);
  74. }
  75. /// <summary>
  76. /// 类型映射
  77. /// </summary>
  78. public static TDestination MapTo<TSource, TDestination>(this TSource source, TDestination destination)
  79. where TSource : class
  80. where TDestination : class
  81. {
  82. if (source == null) return destination;
  83. Mapper.CreateMap<TSource, TDestination>();
  84. return Mapper.Map(source, destination);
  85. }
  86. /// <summary>
  87. /// DataReader映射
  88. /// </summary>
  89. public static IEnumerable<T> DataReaderMapTo<T>(this IDataReader reader)
  90. {
  91. Mapper.Reset();
  92. Mapper.CreateMap<IDataReader, IEnumerable<T>>();
  93. return Mapper.Map<IDataReader, IEnumerable<T>>(reader);
  94. }
  95. }
  96. }

你可以像下面的栗子这样使用:

  1. //对象映射
  2. ShipInfoModel shipInfoModel = ShipInfo.MapTo<ShipInfoModel>();
  3. //列表映射
  4. List< ShipInfoModel > shipInfoModellist = ShipInfoList.MapToList<ShipInfoModel>();

  • 本文作者:GeekPower - Felix Sun
  • 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!