.Net 记一次实体类拷贝效率测试

测试背景(更详细介绍,请参照这篇文章,感谢楼主无私奉献):

有时候为了将实体的字段值赋值给DTO的字段,需要实现复制功能(字段较多的时候,直接硬编码会很痛苦)。一般可以通过硬编码、反射、序列化反序列化实现,但效率都相对较低。今天我们通过表达式树的方式,实现复制功能,顺便和序列化反序列化方法做个性能比对。

DTO:数据传输对象,我们经常用到的一个东西。有时候我们称之为的ViewModel也属于其中之一。以往,我们总是复制实体类型的一些字段 然后单独创建这些对象。

实体类如下:

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

DTO如下:

    public class PersonDTO
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

序列化反序列化如下:

 using Newtonsoft.Json;
 public static class ObjectExtension
    {
        /// <summary>
        /// 序列化、反序列化
        /// </summary>
        /// <typeparam name="TIn"></typeparam>
        /// <typeparam name="TOut"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static TOut Copy<TIn, TOut>(TIn t)
        {
            return JsonConvert.DeserializeObject<TOut>(JsonConvert.SerializeObject(t));
        }

    }

表达式目录树如下:

    using System.Linq.Expressions;
    using System.Runtime.Serialization.Formatters.Binary;

    /// <summary>
    /// 表达式目录树 拷贝方法,必须是同结构类
    /// </summary>
    /// <typeparam name="TIn"></typeparam>
    /// <typeparam name="TOut"></typeparam>
    public class ExpressionGenercMapper<TIn, TOut>
    {
        private static Func<TIn, TOut> _Func = null;
        static ExpressionGenercMapper()
        {
            ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
            List<MemberBinding> memberBindings = 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);
                memberBindings.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);
                memberBindings.Add(memberBinding);
            }
            MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindings.ToArray());
            Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
            {
                    parameterExpression
            });
            _Func = lambda.Compile();
        }

        public static TOut Trans(TIn t)
        {
            return _Func(t);
        }

    }

测试如下:

Person person = new Person()
            {
                Id = 1,
                Name = "张三"
            };

            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            for (int i = 0; i < 100_000; i++)
            {
                PersonDTO personClone = ObjectExtension.Copy<Person, PersonDTO>(person);
            }
            stopwatch.Stop();
            TimeSpan timespan = stopwatch.Elapsed;
            double millisecondsOne = timespan.TotalMilliseconds;

            Stopwatch stopwatch1 = new Stopwatch();
            stopwatch1.Start();
            for (int i = 0; i < 100_000; i++)
            {
                PersonDTO personClone = ExpressionGenercMapper<Person, PersonDTO>.Trans(person);
            }
            stopwatch1.Stop();
            TimeSpan timespan1 = stopwatch1.Elapsed;
            double millisecondsTwo = timespan1.TotalMilliseconds;
            Console.WriteLine($"序列化:{millisecondsOne}s");
            Console.WriteLine($"目录树:{millisecondsTwo}s");

结果如下:

结论:

通过上面的测试可以看出,两者行能相差较大,表达式目录树更适合做数据复制。

谢谢打赏

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值