.NET的DTO映射工具 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添加到项目中了~

二、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的相互转换,让AutoMapper在你的项目里飞一会儿。