背景介绍:
1.在开发中,我们经常需要将实体查询出来的实体转换为页面展示实体,这个页面展示的实体,其实我们口中常说的DTO(Data Tranfer Object)
2.我们查询完数据库数据后,如何转换为DTO呢,抛开手写,就要使用到工具了,今天带来的是一款轻量级的实体转换工具:AutoMapper
3.备注一下,AutoMapper十分强大,自己之前也踩过一些坑,但是我自己平时开发是不使用这个玩意的,我自己写了一套实体转换和映射,但是不代表AutoMapper不好哈,大多数玩家还是可以直接拿来开箱即用的
好了,进入正题,直接上代码,注释都写明白了
使用:
Mapper.Initialize(config =>
{
//默认是同名即转换
var map = config.CreateMap<Student, Person>();
//通过表达式目录树来指定转换规则,下面的含义是:target中的PersonId属性,从source中的StudentId读取
map.ForMember(p => p.PersonId, r => r.MapFrom(x => x.StudentId));
//数据类型不同,也可以转换,只要允许,例如int可以放到string中,string也可以放到int中,但是string如果无法转换为数字,则会报错
map.ForMember("PersonId", r => r.MapFrom("StudentId"));
});
var studentList = GetStudentList();
var personList = Mapper.Map<List<Student>, List<Person>>(studentList);
扩展(大家懂得使用方法后可以自己扩展更多):
using System;
using System.Collections.Generic;
using AutoMapper;
namespace TestAutomapper
{
/// <summary>
/// AutoMapper扩展
/// </summary>
public static class AutomapperExtension
{
/// <summary>
/// 创建映射关系,如果实体包含子实体,子实体也要创建映射关系
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TTarget"></typeparam>
/// <param name="dicCustomerMapping">key是target属性名,value是source属性名(读取value列的填充到key列中)</param>
private static void CreateMap<TSource, TTarget>(Dictionary<string, string> dicCustomerMapping)
{
Mapper.Initialize(config =>
{
var map = config.CreateMap<TSource, TTarget>();
if (dicCustomerMapping != null)
{
foreach (var dicItem in dicCustomerMapping)
{
map = map.ForMember(dicItem.Key, r => r.MapFrom(dicItem.Value));
}
}
});
}
/// <summary>
/// 创建映射关系,如果实体包含子实体,子实体也要创建映射关系
/// </summary>
/// <param name="sourceType"></param>
/// <param name="targetType"></param>
/// <param name="dicCustomerMapping">key是target属性名,value是source属性名(读取value列的填充到key列中)</param>
private static void CreateMap(Type sourceType, Type targetType, Dictionary<string, string> dicCustomerMapping)
{
Mapper.Initialize(config =>
{
var map = config.CreateMap(sourceType, targetType);
if (dicCustomerMapping != null)
{
foreach (var dicItem in dicCustomerMapping)
{
map = map.ForMember(dicItem.Key, r => r.MapFrom(dicItem.Value));
}
}
});
}
/// <summary>
/// 转换核心方法
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TTarget"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
private static TTarget MapLingbug<TSource, TTarget>(TSource source)
{
return Mapper.Map<TSource, TTarget>(source);
}
/// <summary>
/// 实体转换
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TTarget"></typeparam>
/// <param name="source"></param>
/// <param name="dicCustomerMapping"></param>
/// <returns></returns>
public static TTarget MapTo<TSource, TTarget>(this TSource source, Dictionary<string, string> dicCustomerMapping = null)
{
CreateMap<TSource, TTarget>(dicCustomerMapping);
return MapLingbug<TSource, TTarget>(source);
}
/// <summary>
/// 实体包含子实体的转换,除了实体需要映射,子实体也需要映射
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TTarget"></typeparam>
/// <param name="source"></param>
/// <param name="dicCustomerMapping"></param>
/// <param name="childMapList"></param>
/// <returns></returns>
public static TTarget MapTo<TSource, TTarget>(this TSource source, Dictionary<string, string> dicCustomerMapping, List<Tuple<Type, Type, Dictionary<string, string>>> childMapList)
{
CreateMap<TSource, TTarget>(dicCustomerMapping);
childMapList.ForEach(r =>
{
CreateMap(r.Item1, r.Item2, r.Item3);
});
return MapLingbug<TSource, TTarget>(source);
}
/// <summary>
/// 集合转换
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TTarget"></typeparam>
/// <param name="sourceList"></param>
/// <param name="dicCustomerMapping"></param>
/// <returns></returns>
public static List<TTarget> MapTo<TSource, TTarget>(this List<TSource> sourceList, Dictionary<string, string> dicCustomerMapping = null)
{
CreateMap<TSource, TTarget>(dicCustomerMapping);
return MapLingbug<List<TSource>, List<TTarget>>(sourceList);
}
/// <summary>
/// 数组转换
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TTarget"></typeparam>
/// <param name="sourceArray"></param>
/// <param name="dicCustomerMapping"></param>
/// <returns></returns>
public static TTarget[] MapTo<TSource, TTarget>(this TSource[] sourceArray, Dictionary<string, string> dicCustomerMapping = null)
{
CreateMap<TSource, TTarget>(dicCustomerMapping);
return MapLingbug<TSource[], TTarget[]>(sourceArray);
}
}
}
测试扩展:
var studentList = GetStudentList();
var dicMapping = new Dictionary<string, string>()
{
{"PersonId", "StudentId"},//将StudentId映射到PersonId
{"AgeDes","Age" },//将int转换为string映射过去
{"Age","ClassName" }//将string转换为int映射过去
};
var personList = studentList.MapTo<Student, Person>(dicMapping);
实体类和初始化数据代码:
public class Person
{
public int PersonId { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Sex { get; set; }
public DateTime CreateDate { get; set; }
public string AgeDes { get; set; }
}
public class Student
{
public int StudentId { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Sex { get; set; }
public DateTime CreateDate { get; set; }
public string ClassName { get; set; }
public string TeacherName { get; set; }
}
private static List<Student> GetStudentList()
{
char a = ',';
var names = "张三,李四,王五,赵六,田七".Split(a);
var sexs = "男,女".Split(a);
var classNames = "普通一班,奥赛二班,竞赛三班,报送四班".Split(a);
var teacherNames = "张老师,王老师,李老师,孙老师".Split(a);
var r = new Random();
var list = new List<Student>();
for (int i = 0; i < 100; i++)
{
var nameIndex = r.Next(names.Length);
var sexIndex = r.Next(sexs.Length);
var classNameIndex = r.Next(classNames.Length);
var teacherNameIndex = r.Next(teacherNames.Length);
list.Add(new Student()
{
StudentId = i + 1,
Name = names[nameIndex],
Age = r.Next(15, 30),
Sex = sexs[sexIndex],
CreateDate = DateTime.Now,
//ClassName = classNames[classNameIndex],
ClassName = (i + 5).ToString(),
TeacherName = teacherNames[teacherNameIndex]
});
}
return list;
}
Ending~