视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
.NET core高性能对象转换示例代码
2020-11-27 22:34:56 责编:小采
文档


前言

NET Core(开放源代码,跨平台,x-copy可部署等)有许多令人兴奋的方面,其中最值得称赞的就是其性能了。关于对象转换已经有不少轮子(AutoMapper,TinyMapper) .出于项目需要,手动造一个简单轮子。下面话不多说了,来一起看看详细的介绍吧。

示例代码

g>1.采用静态泛型类缓存,避免了拆箱装箱操作。

2.对于转换对象中有,字段名一样但是类型不一样的类时仍可以用

public static class Mapper<TSource, TTarget> where TSource : class where TTarget : class
 {
 public readonly static Func<TSource, TTarget> Map;

 static Mapper()
 {
 if (Map == null)
 Map = GetMap();
 }

 private static Func<TSource, TTarget> GetMap()
 {
 var sourceType = typeof(TSource);
 var targetType = typeof(TTarget);

 var parameterExpression = Expression.Parameter(sourceType, "p");
 var memberInitExpression = GetExpression(parameterExpression, sourceType, targetType);

 var lambda = Expression.Lambda<Func<TSource, TTarget>>(memberInitExpression, parameterExpression);
 return lambda.Compile();
 }

 /// <summary>
 /// 根据转换源和目标获取表达式树
 /// </summary>
 /// <param name="parameterExpression">表达式参数p</param>
 /// <param name="sourceType">转换源类型</param>
 /// <param name="targetType">转换目标类型</param>
 /// <returns></returns>
 private static MemberInitExpression GetExpression(Expression parameterExpression, Type sourceType, Type targetType)
 {
 var memberBindings = new List<MemberBinding>();
 foreach (var targetItem in targetType.GetProperties().Where(x => x.PropertyType.IsPublic && x.CanWrite))
 {
 var sourceItem = sourceType.GetProperty(targetItem.Name);

 //判断实体的读写权限
 if (sourceItem == null || !sourceItem.CanRead || sourceItem.PropertyType.IsNotPublic)
 continue;

 //标注NotMapped特性的属性忽略转换
 if (sourceItem.GetCustomAttribute<NotMappedAttribute>() != null)
 continue;

 var propertyExpression = Expression.Property(parameterExpression, sourceItem);

 //判断都是class 且类型不相同时
 if (targetItem.PropertyType.IsClass && sourceItem.PropertyType.IsClass && targetItem.PropertyType != sourceItem.PropertyType)
 {
 if (targetItem.PropertyType != targetType)//防止出现自己引用自己无限递归
 {
 var memberInit = GetExpression(propertyExpression, sourceItem.PropertyType, targetItem.PropertyType);
 memberBindings.Add(Expression.Bind(targetItem, memberInit));
 continue;
 }
 }

 if (targetItem.PropertyType != sourceItem.PropertyType)
 continue;

 memberBindings.Add(Expression.Bind(targetItem, propertyExpression));
 }
 return Expression.MemberInit(Expression.New(targetType), memberBindings);
 }
 }

3.调用方法如下

 (1)构造样例类

public class A
{
 public int Id { get; set; }
 public string Name { get; set; }
 public C User { get; set; }
 
 /// <summary>
 /// 标注为notmapped特性时,不转换赋值
 /// </summary>
 [System.ComponentModel.DataAnnotations.Schema.NotMapped]
 public D UserA { get; set; }
 
}
 
public class B
{
 public int Id { get; set; }
 public string Name { get; set; }
 public D User { get; set; }<br data-filtered="filtered">
 public D UserA { get; set; }
}
 
public class C
{
 public int Id { get; set; }
 public string Name { get; set; }
}
 
public class D
{
 public int Id { get; set; }
 public string Name { get; set; }
}

  (2) 调用

var a = new A
{
 Id = 1,
 Name = "张三",
 User = new C
 {
 Id = 1,
 Name = "李四"
 }
};<br>
B b = Mapper<A, B>.Map(a);//得到转换结果

4.性能测试

var length = 10000000;
 var listA = new List<A>();
 for (int i = 0; i < length; i++)
 {
 listA.Add(new A
 {
 Id = i,
 Name = "张三",
 User = new C
 {
 Id = i,
 Name = "李四"
 }
 });
 }

 var sw = Stopwatch.StartNew();
 for (int i = 0; i < length; i++)
 {
 var item = listA[i];
 var b = new B
 {
 Id = item.Id,
 Name = item.Name,
 User = new D
 {
 Id = i,
 Name = "李四",
 }
 };
 }
 sw.Stop();
 Console.WriteLine($"原生的时间:{sw.ElapsedMilliseconds}ms");

 //表达式
 Mapper<A, B>.Map(listA[0]);//预先编译缓存
 sw.Restart();
 for (int i = 0; i < length; i++)
 {
 Mapper<A, B>.Map(listA[i]);
 }
 sw.Stop();
 Console.WriteLine($"表达式的时间:{sw.ElapsedMilliseconds}ms");

 //AutoMapper
 AutoMapper.Mapper.Initialize(cfg => cfg.CreateMap<A, B>());
 sw.Restart();
 for (int i = 0; i < length; i++)
 {
 var b = AutoMapper.Mapper.Map<B>(listA[i]);
 }
 sw.Stop();
 Console.WriteLine($"AutoMapper时间:{sw.ElapsedMilliseconds}ms");

 //TinyMapper
 TinyMapper.Bind<A, B>();
 sw.Restart();
 for (int i = 0; i < length; i++)
 {
 var b = TinyMapper.Map<B>(listA[i]);
 }
 sw.Stop();
 Console.WriteLine($"TinyMapper时间:{sw.ElapsedMilliseconds}ms");

 Console.ReadLine();

5. 1000万数据不带子类集结果

6. 1000万数据带子类集结果 

总结

下载本文
显示全文
专题