.NET-001实体类与实体DTO类转换的思考与实现:
几种常见方式:
- 硬编码方式:直接对实体DTO类进行赋值,效率最高,但可维护性差,通用性差。
- 反射,动态获取属性,效率低。
- Json序列化,反序列化:使用Newtonsoft.Json通过JsonConvert.SerializeObject<SourceClass,DestinDTO>(sourceInstance)进行序列化,通过JsonConvert.DeserializeObject
(sSourceClass)来实现,效率很低。 - 使用AutoMapper映射类来实现,Mapper.Initialize初始化,Mapper.Map<SourceClass,DestinDTO>(sourceInstance) 效率高。
- 静态缓存字典+表达式目录树实现:和AutoMapper类效率差不多。
- 泛型缓存+表达式目录树实现:效率仅次于硬编码。
各种方式实现的代码:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using System.Linq.Expressions;
using DynamicExpresso;
using Gremlin.Net.Process.Traversal;
namespace DTOExample {
class Program {
public static Dictionary<string, object> _Dictionary = new Dictionary<string, object>();
static void Main(string[] args) {
Student student = new Student() { Age = 24, ID = 1, Name = "Albert" };
//FirstMethod 使用Newtonsoft.Json序列号反序列化 此种方法效率很低
string sStudent = JsonConvert.SerializeObject(student); //先序列化为字符串
StudentDTO studentDTO = JsonConvert.DeserializeObject<StudentDTO>(sStudent);//反序列化
//SecondMethod 使用automapper映射 专属的类型映射工具,为ORM而生 效率高
Mapper.Initialize(x => x.CreateMap<Student, StudentDTO>());
StudentDTO studentDTO1 = Mapper.Map<Student, StudentDTO>(student);
//不同名称的映射
//Mapper.Initialize(config=> {
// config.CreateMap<Student, StudentDTO>().
// ForMember(dest => dest.DickName, options => options.MapFrom(sou => sou.Name));
//});
//StudentDTO studentDTO2 = Mapper.Map<Student, StudentDTO>(student);
//ThirdMethod 表达式目录树+静态缓存字典
//表达式目录树+静态字典
StudentDTO studentDTO3 = Trans<Student, StudentDTO>(student);
//效率较高,表达式目录树+泛型缓存
StudentDTO studentDTO4 = ExpressionGenericMapper<Student, StudentDTO>.Trans(student);
}
//表达式+静态字典
public static TOut Trans<TIn,TOut>(TIn tIn) {
TOut tOut = Activator.CreateInstance<TOut>();
string key = string.Format("funckey_{0}_{1}", tIn.GetType().Name, tOut.GetType().Name);
if (!_Dictionary.ContainsKey(key)) {
ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
List<MemberBinding> memberBindingsList = new List<MemberBinding>();
foreach (var item in typeof(TOut).GetProperties()) {
MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
MemberBinding memberBinding = Expression.Bind(item, property);
memberBindingsList.Add(memberBinding);
}
foreach (var item in typeof(TOut).GetFields()) {
MemberExpression filed = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
MemberBinding memberBinding = Expression.Bind(item, filed);
memberBindingsList.Add(memberBinding);
}
MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingsList.ToArray());
Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
{
parameterExpression
});
Func<TIn, TOut> func = lambda.Compile();
_Dictionary[key] = func;
}
return ((Func<TIn, TOut>)_Dictionary[key]).Invoke(tIn);
}
}
class Student {
public int ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public void PrintAge() {
Console.WriteLine(Age);
}
}
class StudentDTO {
public int ID { get; set; }
public string Name { get; set; }
//public string DickName { get; set; }
public int Age { get; set; }
public void PrintAge() {
Console.WriteLine(Age);
}
}
//表达式目录树+泛型缓存
public class ExpressionGenericMapper<TIn, TOut> {
private static Func<TIn, TOut> _FUNC = null;
static ExpressionGenericMapper() {
ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
List<MemberBinding> memberBindingsList = new List<MemberBinding>();
foreach (var item in typeof(TOut).GetProperties()) {
MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
MemberBinding memberBinding = Expression.Bind(item, property);
memberBindingsList.Add(memberBinding);
}
foreach (var item in typeof(TOut).GetFields()) {
MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
MemberBinding memberBinding = Expression.Bind(item, property);
memberBindingsList.Add(memberBinding);
}
MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingsList.ToArray());
Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
{
parameterExpression
});
_FUNC = lambda.Compile();//拼装是一次性的
}
public static TOut Trans(TIn tIn) {
return _FUNC(tIn);
}
}
}
心若向阳,何惧风雨。千帆过尽,我想起的不是孤独和路长,而是波澜壮阔的大海和璀璨的星空...