C# 快速高效率复制对象另一种方式 表达式树
1、需求在代码中经常会遇到需要把对象复制一遍,或者把属性名相同的值复制一遍。 比如: Id { ; Name { ; Age { ;</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> StudentSecond
{
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span> Id { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Name { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span> Age { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
}</span></pre>
Student s = new Student() { Age = 20,Id = 1,Name = "Emrys" }; 我们需要给新的Student赋值 Student ss = new Student { Age = s.Age,Id = s.Id,Name = s.Name }; 再或者给另一个类StudentSecond的属性赋值,两个类属性的名称和类型一致。 StudentSecond ss = new StudentSecond { Age = s.Age,Name = s.Name }; 2、解决办法当然最原始的办法就是把需要赋值的属性全部手动手写。这样的效率是最高的。但是这样代码的重复率太高,而且代码看起来也不美观,更重要的是浪费时间,如果一个类有几十个属性,那一个一个属性赋值岂不是浪费精力,像这样重复的劳动工作更应该是需要优化的。 2.1、反射反射应该是很多人用过的方法,就是封装一个类,反射获取属性和设置属性的值。 TOut TransReflection调用:StudentSecond ss= TransReflection 调用一百万次耗时: 2.2、序列化序列化的方式有很多种,有二进制、xml、json等等,今天我们就用Newtonsoft的json进行测试。 调用:StudentSecond ss= JsonConvert.DeserializeObject 调用一百万次耗时: 从这可以看出序列化和反射效率差别不大。 3、表达式树3.1、简介关于表达式树不了解的可以百度。 也就是说复制对象也可以用表达式树的方式。 Expression这样的方式我们可以达到同样的效果。 有人说这样的写法和最原始的复制没有什么区别,代码反而变多了呢,这个只是第一步。 3.2、分析代码我们用ILSpy反编译下这段表达式代码如下: 那么也就是说我们只要用反射循环所有的属性然后Expression.Bind所有的属性。最后调用Compile()(s)就可以获取正确的StudentSecond。 看到这有的人又要问了,如果用反射的话那岂不是效率很低,和直接用反射或者用序列化没什么区别吗? 当然这个可以解决的,就是我们的表达式树可以缓存。只是第一次用的时候需要反射,以后再用就不需要反射了。 3.3、复制对象通用代码为了通用性所以其中的Student和StudentSecond分别泛型替换。 Dictionary<,> _Dic = Dictionary<,> </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> TOut TransExp<TIn,TOut><span style="color: #000000;">(TIn tIn)
{
</span><span style="color: #0000ff;">string</span> key = <span style="color: #0000ff;">string</span>.Format(<span style="color: #800000;">"</span><span style="color: #800000;">trans_exp_{0}_{1}</span><span style="color: #800000;">"</span>,<span style="color: #0000ff;">typeof</span>(TIn).FullName,<span style="color: #0000ff;">typeof</span><span style="color: #000000;">(TOut).FullName);
</span><span style="color: #0000ff;">if</span> (!<span style="color: #000000;">_Dic.ContainsKey(key))
{
ParameterExpression parameterExpression </span>= Expression.Parameter(<span style="color: #0000ff;">typeof</span>(TIn),<span style="color: #800000;">"</span><span style="color: #800000;">p</span><span style="color: #800000;">"</span><span style="color: #000000;">);
List</span><MemberBinding> memberBindingList = <span style="color: #0000ff;">new</span> List<MemberBinding><span style="color: #000000;">();
</span><span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> item <span style="color: #0000ff;">in</span> <span style="color: #0000ff;">typeof</span><span style="color: #000000;">(TOut).GetProperties())
{ </span> if (!item.CanWrite) continue;</pre>
= Expression.Property(parameterExpression,=
调用:StudentSecond ss= TransExp 调用一百万次耗时: 3.4、利用泛型的特性再次优化代码<div class="cnblogs_code"> TransExpV2 调用:StudentSecond ss= TransExpV2 调用一百万次耗时: 4、总结效率与书写方式二者兼备的方法之一,总之比传统的序列化和反射更加优秀。 推荐。 (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net-mvc-2 – ::%:和%=与嵌套代码(表达式)块相同的
- asp.net %$...%语法
- asp.net-mvc – 是否有任何基于ASP.NET MVC订阅的入门工具包
- asp.net-mvc-4 – MVC 4中的HttpContext.Current.Request.I
- ASP.NET MVC 4实体框架6 SQL Compact Edition 4.0部署无需安
- ASP.NET MVC – Ajaxified RenderAction
- asp.net – 使用Visual Studio 2015检测gulp中的发布/调试
- 在Build上自动停止/重新启动ASP.NET开发服务器
- asp.net – 使用AutoGenerateColumns = true操作GridView中
- asp.net – N层和SOA架构有什么区别?
- asp.net-mvc – ASP.NET MVC路由:如何定义自定义
- 什么是ASP.NET vNext?
- asp.net-web-api2 – Web Api 2 Post – UrlHelp
- ASP.NET MVC的排队解决方案
- ASP.NET CheckBoxList DataBinding问题
- asp.net-mvc – 建立与SQL Server的连接时发生网
- asp.net – 使用ASP:文本框作为
- asp.net-mvc – ASP.Net MVC 2验证是否需要更多的
- ASP.NET – C#vs VB.NET – 间接差异和您最初可能
- asp.net – 在VS Code中指定localhost端口的位置
