.net core 高性能对象映射
关于对象转换已经有不少轮子(AutoMapper,TinyMapper) .出于项目需要,手动造一个简单轮子。先贴代码
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; }
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 = "李四"
}
};
B b = Mapper<A, B>.Map(a);//得到转换结果
4.性能测试
var length = ;
var listA = new List<A>();
for (int i = ; i < length; i++)
{
listA.Add(new A
{
Id = i,
Name = "张三",
User = new C
{
Id = i,
Name = "李四"
}
});
} var sw = Stopwatch.StartNew();
for (int i = ; 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[]);//预先编译缓存
sw.Restart();
for (int i = ; 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 = ; 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 = ; i < length; i++)
{
var b = TinyMapper.Map<B>(listA[i]);
}
sw.Stop();
Console.WriteLine($"TinyMapper时间:{sw.ElapsedMilliseconds}ms"); Console.ReadLine();
5. 1000万数据不带子类集结果

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

.net core 高性能对象映射的更多相关文章
- [非专业翻译] 高性能对象映射框架 - Mapster
[非专业翻译] 高性能对象映射框架 - Mapster 系列介绍 [非专业翻译] 是对没有中文文档进行翻译的系列博客,文章由机翻和译者自己理解构成,和原文相比有所有不通,但意思基本一致. 因个人能力有 ...
- C# 高性能对象映射(表达式树实现)
前言 上篇简单实现了对象映射,针对数组,集合,嵌套类并没有给出实现,这一篇继续完善细节. 开源对象映射类库映射分析 1.AutoMapper 实现原理:主要通过表达式树Api 实现对象映射 优点: . ...
- C# 高性能对象映射
1.之前在使用AutoMapper 框架感觉用着比较不够灵活,而且主要通过表达式树Api 实现对象映射 ,写着比较讨厌,当出现复杂类型和嵌套类型时性能直线下降,甚至不如序列化快. 2.针对AutoMa ...
- ASP.NET CORE 中使用AutoMapper进行对象映射
ASP.NET CORE 中使用AutoMapper进行对象映射 1.什么是AutoMapper? AutoMapper是基于对象到对象约定的映射工具,常用于(但并不仅限制于)把复杂的对象模型转为DT ...
- ASP.NET Core实现对象自动映射-AgileMapper
我们为什么要在对象之间做映射 处于耦合性或者安全性考虑或者性能考虑我们不希望将Model模型传递给他们,我们会在项目中创建一些DTO(Data transfer object数据传输对象),进行数据的 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - 用AutoMapper搞定对象映射
上一篇文章(https://www.cnblogs.com/meowv/p/12961014.html)集成了定时任务处理框架Hangfire,完成了一个简单的定时任务处理解决方案. 本篇紧接着来玩一 ...
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十三 || DTOs 对象映射使用,项目部署Windows+Linux完整版
更新 很多小伙伴在用 IIS 发布的时候,总是会有一些问题,文章下边 #autoid-6-0-0 我也简单的动图展示了,如何 publish 到 IIS 的过程,如果你能看懂,却发现自己的项目有问题的 ...
- 关于对象映射(Dto->model) 思路的一些想法
最近粗浅的学习了下AutoMapper 这个做对象映射的第三方工具,觉得非常方便使用,所以简单的总结了一下我能想到的简单的对象映射的方式. 占时先不考虑源对象成员到目标对象成员的指定映射(即成员名不一 ...
- 一:ORM关系对象映射(Object Relational Mapping,简称ORM)
狼来的日子里! 奋发博取 10)django-ORM(创建,字段类型,字段参数) 一:ORM关系对象映射(Object Relational Mapping,简称ORM) ORM分两种: DB fir ...
随机推荐
- 利用CopyOnWriteArrayList解决并发修改异常问题
一.需求 多个线程再获取同一个集合里面的数据同时,修改集合中的数据. 二.有问题的写法 package com.duchong.juc; import java.util.ArrayList; imp ...
- vue -Missing space before value for key 'path'vue.js解决空格报错
webpack.base.config.js文件注释掉下面的东西!! module: { rules: [ /*{ test: /\.(js|vue)$/, lo ...
- RouterOS DNS劫持(转)
什么是DNS劫持 DNS劫持就是通过技术手段,来控制用户解析域名的IP地址.举个例子,正常解析域名www.awolf.net时应该返回IP:64.64.30.60:但现在通过DNS劫持,使域名www. ...
- 第二天:让我们一起来玩玩css精灵(css sprites)
1.效果图 2.html代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://ww ...
- linux服务器中Apache隐藏index.php失败
可以通过URL重写隐藏应用的入口文件index.php,下面是相关服务器的配置参考: [Apache] httpd.conf配置文件中加载了mod_rewrite.so模块 AllowOverride ...
- angularjs学习访问服务器(5)
(1) 后台AngularController.java代码 package com.amy.controller; import java.util.ArrayList; import java.u ...
- -other linker flags - 详解
• 值:-objC,-all_load,-force_load • -objC: 在iOS 中,使用-all_load时,如果静态库中有类别时会出问题,使用其他两个值则不会有问题. • -al ...
- python基础之-数据类型
Python3 数字(Number) Python 数字数据类型用于存储数值. 数据类型是不允许改变的,这就意味着如果改变数字数据类型得值,将重新分配内存空间. 以下实例在变量赋值时 Number 对 ...
- code1214 线段覆盖
贪心 把线段们按终止点b的先后排序,b小的在前面,b一样随便 然后设r为当前最大的b 每加入一条新的线段i,判断是否重合(i.a>=r) 如果重合就舍弃i,否则把i加入,ans++,更新r:r= ...
- [Excel]鼠标右键菜单没有新建Word、Excel、PPT怎么办?
很多朋友在安装好Office(2010或2013等)之后,发现右键新建中没有Word.Excel.PowerPoint等项,但是自己的Office却明明安装好了.这个时候该怎么办呢?这里,本文为大家提 ...