.net core 高性能对象转换

castyuan 2018-07-09 原文

.net core 高性能对象转换

关于对象转换已经有不少轮子(AutoMapper,TinyMapper) .出于项目需要,手动造一个简单轮子。先贴代码

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

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

  

 1     public static class Mapper<TSource, TTarget> where TSource : class where TTarget : class
 2     {
 3         public readonly static Func<TSource, TTarget> Map;
 4 
 5         static Mapper()
 6         {
 7             if (Map == null)
 8                 Map = GetMap();
 9         }
10 
11         private static Func<TSource, TTarget> GetMap()
12         {
13             var sourceType = typeof(TSource);
14             var targetType = typeof(TTarget);
15 
16             var parameterExpression = Expression.Parameter(sourceType, "p");
17             var memberInitExpression = GetExpression(parameterExpression, sourceType, targetType);
18 
19             var lambda = Expression.Lambda<Func<TSource, TTarget>>(memberInitExpression, parameterExpression);
20             return lambda.Compile();
21         }
22 
23         /// <summary>
24         /// 根据转换源和目标获取表达式树
25         /// </summary>
26         /// <param name="parameterExpression">表达式参数p</param>
27         /// <param name="sourceType">转换源类型</param>
28         /// <param name="targetType">转换目标类型</param>
29         /// <returns></returns>
30         private static MemberInitExpression GetExpression(Expression parameterExpression, Type sourceType, Type targetType)
31         {
32             var memberBindings = new List<MemberBinding>();
33             foreach (var targetItem in targetType.GetProperties().Where(x => x.PropertyType.IsPublic && x.CanWrite))
34             {
35                 var sourceItem = sourceType.GetProperty(targetItem.Name);
36 
37                 //判断实体的读写权限
38                 if (sourceItem == null || !sourceItem.CanRead || sourceItem.PropertyType.IsNotPublic)
39                     continue;
40 
41                 //标注NotMapped特性的属性忽略转换
42                 if (sourceItem.GetCustomAttribute<NotMappedAttribute>() != null)
43                     continue;
44 
45                 var propertyExpression = Expression.Property(parameterExpression, sourceItem);
46 
47                 //判断都是class 且类型不相同时
48                 if (targetItem.PropertyType.IsClass && sourceItem.PropertyType.IsClass && targetItem.PropertyType != sourceItem.PropertyType)
49                 {
50                     if (targetItem.PropertyType != targetType)//防止出现自己引用自己无限递归
51                     {
52                         var memberInit = GetExpression(propertyExpression, sourceItem.PropertyType, targetItem.PropertyType);
53                         memberBindings.Add(Expression.Bind(targetItem, memberInit));
54                         continue;
55                     }
56                 }
57 
58                 if (targetItem.PropertyType != sourceItem.PropertyType)
59                     continue;
60 
61                 memberBindings.Add(Expression.Bind(targetItem, propertyExpression));
62             }
63             return Expression.MemberInit(Expression.New(targetType), memberBindings);
64         }
65     }

View Code

 

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 = 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");

            Console.ReadLine();

 

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

 

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

 

发表于 2018-07-09 19:23 costyuan 阅读() 评论() 编辑 收藏

 

版权声明:本文为castyuan原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/castyuan/p/9285101.html

.net core 高性能对象转换的更多相关文章

  1. C# 运用多元一次方程解决问题

    高斯消元运用 最近项目涉及到一个需求,需要把指定数量的多个商品,混合装入到多个不同型号的箱子中(每种型号的箱子 […]...

  2. C# 对象映射研究(表达式树)

    C# 对象映射研究(表达式树) 前言   上篇简单实现了对象映射,针对数组,集合,嵌套类并没有给出实现,这一篇 […]...

  3. EFCore扩展Update方法(实现 Update User SET Id=Id+1)

    EFCore扩展Update方法(实现 Update User SET Id = Id + 1) 源码地址(g […]...

  4. EFCore扩展Select方法(自动映射自定义实体)

    EFCore扩展Select方法(自动映射自定义实体)  通常用操作数据库的时候查询返回的字段是跟 我们的定义 […]...

随机推荐

  1. AVFoundation的使用

    AVFoundation的使用 AVFoundation的使用   2013-05-03 14:50:21|  […]...

  2. c语言中求数组的最小值和最大值

      #include <stdio.h> int main(void) { int a[7] = […]...

  3. linux vi 替换命令

    久了没用vi 命令都忘了,到网上找了些,记录下,以下内容出自网络,来源已经不详. vi/vim 中可以使用 : […]...

  4. # Python 3 进阶 —— print 打印和输出

    在 Python 中,print 可以打印所有变量数据,包括自定义类型。 在 2.x 版本中,print 是个 […]...

  5. 【二代示波器教程】第15章 FreeRTOS操作系统版本二代示波器实现

    第15章     FreeRTOS操作系统版本二代示波器实现 本章教程为大家讲解FreeRTOS操作系统版本的 […]...

  6. [导入]在线视频录制时如何加入自己机器上播放的音乐

    很多网友录制视频的时候发现自己播放的音乐没有录进来,以为非要用音箱放出声用麦克风来录,其实这样的效果很差,而且 […]...

  7. Android资源管理利器Resources和AssetManager

    前言  :        Android工程在运行的时候往往需要引用资源。使用 Resources 来获取 r […]...

  8. 「组合数的计算方法」

    「组合数的计算方法」 组合数的计算方法 1 考虑用 \(\operatorname{DP}\) 求解,设 \( […]...

展开目录

目录导航