zoukankan      html  css  js  c++  java
  • 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(两个类型之间的映射)

    Mapper.CreateMap<AddressDto, Address>();
                 AddressDto dto = new AddressDto
                  {
                      Country = "China",
                      City = "ShangHai",
                      Street = "JinZhong Street"
                  };
    Address address = Mapper.Map<AddressDto,Address>(Dto);

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

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

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

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

    源类型List<Address>,目标类型List<AddressDto>:

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

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

    public class ProductBll
    
    {
            Public IProductRepository productRepository{ set; get; }
            public ProductDTO CreateProduct(ProductDTO productDTO)
            {
                Mapper.CreateMap<ProductDTO, Product>();
                Product product = Mapper.Map<ProductDTO, Product>(productDTO);
                productRepository.AddProduct(product);
                return productDTO;
            }
    
            public List<ProductDTO> GetProduct()
            {
                Mapper.CreateMap<Product, ProductDTO>();
                List<ProductDTO> arr = new List<ProductDTO>();
                productRepository.GetProduct().ForEach(i =>
                {
                    arr.Add(Mapper.Map<Product, ProductDTO>(i));
                });
                return arr;
            }
    
             public ProductDTO ModifyProduct(ProductDTO productDTO)
            {
                Mapper.CreateMap<ProductDTO, Product>();
                Product product = Mapper.Map<ProductDTO, Product>(productDTO);
                productRepository.ModifyProduct(product);
                return productDTO;
            }
    }

    三、让AutoMapper使用变得简单

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

    using System.Collections;
    using System.Collections.Generic;
    using System.Data;
    using AutoMapper;
    namespace Infrastructure.Utility
    
    {
        /// <summary>
        /// AutoMapper扩展帮助类
        /// </summary>
        public static class AutoMapperHelper
        {
            /// <summary>
            ///  类型映射
            /// </summary>
            public static T MapTo<T>(this object obj)
            {
                if (obj == null) return default(T);
                Mapper.CreateMap(obj.GetType(), typeof(T));
                return Mapper.Map<T>(obj);
            }
            /// <summary>
            /// 集合列表类型映射
            /// </summary>
            public static List<TDestination> MapToList<TDestination>(this IEnumerable source)
            {
                foreach (var first in source)
                {
                    var type = first.GetType();
                    Mapper.CreateMap(type, typeof(TDestination));
                    break;
                }
                return Mapper.Map<List<TDestination>>(source);
            }
            /// <summary>
            /// 集合列表类型映射
            /// </summary>
            public static List<TDestination> MapToList<TSource, TDestination>(this IEnumerable<TSource> source)
            {
                //IEnumerable<T> 类型需要创建元素的映射
                Mapper.CreateMap<TSource, TDestination>();
                return Mapper.Map<List<TDestination>>(source);
            }
            /// <summary>
            /// 类型映射
            /// </summary>
            public static TDestination MapTo<TSource, TDestination>(this TSource source, TDestination destination)
                where TSource : class
                where TDestination : class
            {
               if (source == null) return destination;
                Mapper.CreateMap<TSource, TDestination>();
                return Mapper.Map(source, destination);
            }
            /// <summary>
            /// DataReader映射
            /// </summary>
            public static IEnumerable<T> DataReaderMapTo<T>(this IDataReader reader)
            {
                Mapper.Reset();
                Mapper.CreateMap<IDataReader, IEnumerable<T>>();
                return Mapper.Map<IDataReader, IEnumerable<T>>(reader);
            }
        }
    }

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

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

    小结

    在项目中多使用DTO实现表现层与领域Model的解耦,用AutoMapper来实现DTO与领域Model的相互转换。

  • 相关阅读:
    Java实现 LeetCode 697 数组的度(类似于数组的map)
    Java实现 LeetCode 697 数组的度(类似于数组的map)
    Java实现 LeetCode 697 数组的度(类似于数组的map)
    Java实现 LeetCode 696 计数二进制子串(暴力)
    Java实现 LeetCode 696 计数二进制子串(暴力)
    Java实现 LeetCode 696 计数二进制子串(暴力)
    Java实现 LeetCode 695 岛屿的最大面积(DFS)
    Java实现 LeetCode 695 岛屿的最大面积(DFS)
    PHP serialize() 函数
    PHP print_r() 函数
  • 原文地址:https://www.cnblogs.com/dongh/p/8257907.html
Copyright © 2011-2022 走看看