接手的项目还在用 TinyMapper 的一个早期版本用来做自动映射工具,TinyMapper 虽然速度快,但在配置里不能转换类型,比如 deleted 在数据库中用 0、1 表示,转换成实体模型时没法转换成 bool 类型,就为了这一个属性,就必须手写代码人工转换(怪不得有些 Mapper 作者认为 TinyMapper 是一个 toy)。
  于是试一试 AutoMapper,可是这货需要提前注册所有的映射关系,程序员本来就已经很累了。。。(最新版 TinyMapper 也要求提前注册所有映射关系)。
  找出以前使用过的 ValueInjecter,可扩展性很强,使用反射来实现。虽然我认为对现在处理器性能而言,快慢已经不太重要了,但它速度实在太慢了,有些测试项目消耗时间是 json反序列化的一半,TinyMapper 和 AutoMapper 均使用 emit 实现,非常接近手写代码的速度了。
  在 nuget.org 上找了找,还发现两个非常不错的 mapper:
  1. UltraMapper 不需要提前注册映射关系,而且使用 ReferenceTracking 解决了循环问题。
  2. HigLabo.Mapper 也不需要提前注册映射关系(看来牛人都对提前注册很不爽),支持 object 转换为Dictionary,提出了 PostAction 概念(自动映射出目标对象后,还可以执行自定义动作进行手工赋值,这样就不需要费力实现 Flattening 什么的了)。但试用过程中,发现不能实现 Array 到 List 的转换,而且作者也不打算改。。。

  既然各个 Mapper 都不太顺手,并且这段时间疫情封控,于是决定自己手撸一个POCO的 Mapper,目标如下:
  1. 不需要提前注册映射关系
  2. 像 json序列化/反序列化一样,同名属性尽可能映射(比如 int? 到 enum)
  3. 增加 HigLabo.Mapper的PostAction概念
  4. 使用 表达式树/Emit 提高速度

  编写过程中参考了 TinyMapper 和UltraMapper的代码,使用示例:

 1     public class Person
2 {
3 public int Id { get; set; }
4
5 public string Name { get; set; }
6 // Same Name, different type
7 public byte? Age { get; set; }
8 }
9
10 public class PersonDto
11 {
12 public int Id { get; set; }
13
14 public string Name { get; set; }
15
16 public int? Age { get; set; }
17
18 public string Description { get; set; }
19 }
20
21 class Program
22 {
23 static void Main(string[] args)
24 {
25 // register PostAction
26 ZK.Mapper.SimpleMapper.Default.SetPostAction<Person, PersonDto>((p, dto) =>
27 {
28 if (dto == null)
29 {
30 return dto;
31 }
32 dto.Description = p.Age.HasValue ? $"{p.Name} age is {p.Age}" : $"{p.Name} age is unknown";
33 return dto;
34 });
35
36 var p = new Person()
37 {
38 Id = 1,
39 Name = "john",
40 Age = 32
41 };
42
43 var dto = ZK.Mapper.SimpleMapper.Default.Map<PersonDto>(p);
44 Console.WriteLine(dto.Description);
45 }
46 }

  写写这里面的总结吧
  1. 内部Mapper都是泛型的,但使用时传入的source很可能是 object,所以都是使用 反射创建泛型化的Mapper实例,然后建立TypePair的对应关系,这样就解偶了泛型
  2. Emit 和 表达式树原理都是一样的,建立IL代码,所以效率非常接近
  3. 如果能像 AutoMapper 那样提前注册所有映射关系,速度优化的手段会更多,估计这也是 TinyMapper 转成提前注册的原因吧。很多 Mapper 的性能测试都号称比 AutoMapper 快,但引用的都是老版本的 AutoMapper,但现在 AutoMapper 非常快,在一些简单测试里赶上了 TinyMapper。如果添加了很多特色功能,却很拖累速度。当然我还是觉得只要不是数量级的差距,都不太重要。
  4. 我的潜意识里 SimpleMapper 就为解决当前项目的问题,比如从数据库中读出来对象,映射成Dto后,就不会被再使用了,所以SimpleMapper默认是浅拷贝。所以我也不打算发布到nuget。
  5. SimpleMapper 功能不多,也没有为性能做太多优化,所以结构比较清晰,有兴趣的朋友阅读起来应该不难。

  SimpleMapper 代码地址

重复造轮子 SimpleMapper的更多相关文章

  1. 避免重复造轮子的UI自动化测试框架开发

    一懒起来就好久没更新文章了,其实懒也还是因为忙,今年上半年的加班赶上了去年一年的加班,加班不息啊,好了吐槽完就写写一直打算继续的自动化开发 目前各种UI测试框架层出不穷,但是万变不离其宗,驱动PC浏览 ...

  2. GitHub Android 最火开源项目Top20 GitHub 上的开源项目不胜枚举,越来越多的开源项目正在迁移到GitHub平台上。基于不要重复造轮子的原则,了解当下比较流行的Android与iOS开源项目很是必要。利用这些项目,有时能够让你达到事半功倍的效果。

    1. ActionBarSherlock(推荐) ActionBarSherlock应该算得上是GitHub上最火的Android开源项目了,它是一个独立的库,通过一个API和主题,开发者就可以很方便 ...

  3. 第27篇 重复造轮子---模拟IIS服务器

    在写程序的时候,重复造轮子是程序员的一个大忌,很多人对重复造轮子持有反对的态度,但是我觉得这个造轮子的过程,是对于现有的知识的一个深入的探索的过程,虽然我们不可能把轮子造的那么的完善,对于现在有的东西 ...

  4. 重复造轮子,编写一个轻量级的异步写日志的实用工具类(LogAsyncWriter)

    一说到写日志,大家可能推荐一堆的开源日志框架,如:Log4Net.NLog,这些日志框架确实也不错,比较强大也比较灵活,但也正因为又强大又灵活,导致我们使用他们时需要引用一些DLL,同时还要学习各种用 ...

  5. Light libraries是一组通用的C基础库,目标是为减少重复造轮子而写(全部用POSIX C实现)

    Light libraries是一组通用的C基础库,目标是为减少重复造轮子而写实现了日志.原子操作.哈希字典.红黑树.动态库加载.线程.锁操作.配置文件.os适配层.事件驱动.工作队列.RPC.IPC ...

  6. 重复造轮子系列——基于Ocelot实现类似支付宝接口模式的网关

    重复造轮子系列——基于Ocelot实现类似支付宝接口模式的网关 引言 重复造轮子系列是自己平时的一些总结.有的轮子依赖社区提供的轮子为基础,这里把使用过程的一些觉得有意思的做个分享.有些思路或者方法在 ...

  7. 重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印

    重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印 一.引言 桌面端系统经常需要对接各种硬件设备,比如扫描器.读卡器.打印机等. 这里介绍下桌面端 ...

  8. Meteva——让预报检验不再重复造轮子

    更多精彩,请点击上方蓝字关注我们! 检验是什么?****预报准确率的客观表达 说到天气预报,你最先会想到什么? 早上听了预报,带了一天伞却没下一滴雨的调侃? 还是 "蓝天白云晴空万里突然暴风 ...

  9. 答应我,用了这个jupyter插件,别再重复造轮子了

    1 简介 在使用Python.R等完成日常任务的过程中,可能会经常书写同样或模式相近的同一段代码,譬如每次使用matplotlib绘制图像的时候可以在开头添加下面两行代码来解决中文乱码等显示问题: p ...

随机推荐

  1. 记一次 .NET 差旅管理后台 CPU 爆高分析

    一:背景 1. 讲故事 前段时间有位朋友在微信上找到我,说他的 web 系统 cpu 运行一段时候后就爆高了,让我帮忙看一下是怎么回事,那就看吧,声明一下,我看 dump 是免费的,主要是锤炼自己技术 ...

  2. NC202498 货物种类

    NC202498 货物种类 题目 题目描述 某电商平台有 \(n\) 个仓库,编号从 \(1\) 到 \(n\) . 当购进某种货物的时候,商家会把货物分散的放在编号相邻的几个仓库中. 我们暂时不考虑 ...

  3. 聊聊Netty那些事儿之从内核角度看IO模型

    从今天开始我们来聊聊Netty的那些事儿,我们都知道Netty是一个高性能异步事件驱动的网络框架. 它的设计异常优雅简洁,扩展性高,稳定性强.拥有非常详细完整的用户文档. 同时内置了很多非常有用的模块 ...

  4. linux服务配置IP或者说可以远程连接

    切换目录 cd /etc/sysconfig/network-scripts ls查看当前目录下的东西 找到ipcfg- 开头的,而且不是iocfg-lo,而上图就是那个ifcfg-ens33. 则进 ...

  5. Kafka Topic Partition Offset 这一长串都是啥?

    摘要:Offset 偏移量,是针对于单个partition存在的概念. 本文分享自华为云社区<Kafka Topic Partition Offset 这一长串都是啥?>,作者: gent ...

  6. WebWorker:工作者线程初探

    WebWorker:工作者线程初探 参考资料: 1.Web Worker 使用教程 - 阮一峰:http://www.ruanyifeng.com/blog/2018/07/web-worker.ht ...

  7. word count的reduce过程以及项目打包部署

    map过程已经写完了,上面那个流程我们涉及到了泛型以及序列化,我们要知道每个参数代表的含义,这样有助于我们理解整个流程. 下面我们开始reduce,这个过程我们要把map输出的键值对把key值相同的放 ...

  8. linux-0.11分析:boot文件 head.s 第三篇随笔

    head.s 参考 [github这个博主的][ https://github.com/sunym1993/flash-linux0.11-talk ] 改变栈顶位置 _pg_dir: startup ...

  9. C++封装静态链接库和使用

    零碎记事 距离上次发博客已经有一年半了,转眼间我也是从做图像研究到了做游戏开发,说起来看看前面的博文,本来就有前兆的东西呢(笑)......因为主要还是在使用虚幻引擎,所以C++的东西会碰到多一些. ...

  10. AtCoder Educational DP Contest 总结

    前言 感觉都初一升初二了,再做这个题是不是有点太菜了啊-- 里面大概都是些 DP 板子题(确信,题目质量还挺高的,不过不涉及太难的优化(实际上只有最后一题是斜率优化). 不管了,还是写个 blog 来 ...