出處:http://www.cnblogs.com/WeiGe/p/3835523.html
先說說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>();